标签:
Unix I/O:简单低级的应用接口,使所有输入输出都以统一的方式执行。
--open:进程通过调用open函数来打开一个已存在的文件或创建一个新文件。
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int open(char *filename, int flags, mode_t mode);
返回:若成功则为新文件描述符,若出错则为-1。
open函数将filename转换为一个文件描述符,并返回描述符数字。返回的描述符是在进程中当前没有打开的最小描述符。
flags参数指明进程打算如何访问这个文件:
以只读的方式打开一个已存在的文件:
fd = Open("foo.txt, O_RDONLY, 0");
打开一个已存在的文件,并在后面添加一些数据:
fd = Open("foo.txt, O_WRONLY|O_APPEND, 0");
-- close:进程通过调用close函数关闭一个打开的文件。
#include<unistd.h>
int close(int fd);
返回:若成功则为0,若出错则为-1。
关闭一个已关闭的描述符会出错。
-- read和write函数:应用程序通过分别调用read和write函数来执行输入和输出。
#include<unistd.h>
ssize_t read(int fd, void *buf, size_t n);
返回:若成功则为读的字节数,若EOF则为0,若出错则为-1。
ssize_t write(int fd, const void *buf, size_t n);
返回:若成功则为写的字节数,若出错则为-1。
注:"csapp.h"是《深入理解计算机系统》这本书写的头文件,运行代码时需要将该头文件下载并移到/usr/include中。
-- ssize_ t 和 size_t 的区别
-- RIO包:自动处理不足值,提供两类不同的函数
-- RIO的无缓冲的输入输出函数
应用程序通过调用rio_ readn和rio_ writen函数可以在存储器和文件之间直接传送数据。
#include"csapp.h"
ssize_ t rio_ readn(int fd, void *usrbuf, size_t n);
ssize_ t rio_ writen(int fd, void *usrbuf, size_t n);
返回:若成功则为传送的字节数,若EOF则为0(只对rio_ readn而言),若出错则为-1。
rio_ readn函数从描述符fd的当前文件位置最多传送n个字节到存储器位置usrbuf。rio_ writen函数从存储器位置usrbuf传送n个字节到描述符fd。
-- RIO的带缓冲的输入函数
一个文本行就是一个由换行符结尾的ASCII码字符序列。
调用包装函数rio_ readlineb,从一个内部读缓冲区拷贝一个文本行,当缓冲区变空时会自动调用read重新填满缓冲区。
#include"csapp.h"
void rio_ readlineb(rio_t *rp, int fd);
ssize_ t rio_ readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
ssize_ t rio_ readnb(rio_t *rp, void *usrbuf, size_t n);
返回:若成功则为读的字节数,若EOF则为0,若出错则为-1。
-- 应用程序能通过调用stat和fstat函数检索到关于文件的信息(元数据)。
#include<unistd.h>
#include<sys/stat.h>
int stat(const char *filename, struct stat *buf);
int fstat(int fd, struct stat *buf);
返回:若成功则为0,若出错则为-1。
-- stat数据结构成员:st_ mode、st_ size……
st_ size成员包含了文件的字节数大小,st_ mode成员编码了文件访问许可位和文件类型。
-- 内核用三个相关的数据结构来表示打开的文件:
多个描述符可以通过不同的文件表表项来引用同一个文件。每个描述符都有它自己的文件位置,所以对不同描述符的读操作可以从文件的不同位置获取数据。
调用fork后,子进程有一个父进程描述符表的副本,共享相同的文件位置。在内核删除相应文件表项之前,父子进程必须都关闭它们的描述符。
I/O重定向操作符:允许用户将磁盘文件和标准输入输出联系起来。I/O重定向可使用dup2函数工作。
#include<unistd.h>
int dup2(int oldfd, int newfd);
返回:若成功则为非负的描述符,若出错则为-1。
dup2函数拷贝描述符表表项oldfd到描述符表表项newfd,覆盖描述符表表项newfd以前的内容。如果newfd已经打开了,dup2会在拷贝oldfd之前关闭newfd。
标准I/O库提供打开和关闭文件的函数(fopen和fclose)、读和写字节的函数(fread和fwrite)、读和写字符串的函数(fgets和fputs),以及复杂的格式化的I/O函数(scanf和printf)。
-- 错误处理包装函数
定义:给定某个基本的系统级函数foo,定义一个有相同参数、只不过开头字母大写的包装函数Foo。包装函数调用基本函数并检查错误。如果包装函数发现错误,则打印一条信息并终止进程。否则它返回到调用者。
-- Unix系统中的错误处理
三种风格:
-- 错误处理包装函数
Unix风格:
pid_t Wait(int *status)
{
pid_t pid;
if(pid = wait(status)<0)
unix_error("wait error");
return pid;
}
Posix风格:
void Pthread_detach(pthread_t tid)
{
int rc;
if(rc=pthread_detach(tid) != 0)
posix_error(rc,"Pthread_detach error");
}
DNS风格:
struct hostent *Gethostbyname(const char *name)
{
struct hostname *p;
if((p = gethostbyname(name)) == NULL)
dns_error("Gethostbyname error");
return p;
}
--什么是进程:一个执行中的程序的实例,系统中每个程序都运行在某个进程的上下文中。
--进程提供给应用程序的关键抽象
--什么是并发:多个流并发的执行的一般现象称为并发(一段时间内P1、P2交替运行)
--并行流:并发流的真子集,两个流并发地运行在不同的处理器核或计算机上,并行地运行且并行地执行。
--获取进程ID
#include<sys/types.h>
#include<unistd.h>
pit_t getpid(void);//返回调用进程的PID
pit_t getppid(void);//返回它的父进程的PID
--创建和终止进程
进程三态:
父进程通过调用fork函数创建一个新的运行子程序
#include<sys/types.h>
#include<unistd.h>
pid_t fork(void);
子进程返回0,父进程返回子进程的PID(大于0),出错返回-1。
注:父进程调用fork时,子进程可以读写父进程中打开的任何文件,父进程和新建的子进程最大的区别在于他们有不同的PID。
***fork函数
特点:只被调用一次,返回两次。一次在调用父进程中,返回子进程的PID;一次在新建的子进程中,返回0。
《深入理解计算机系统》
《嵌入式Linux应用程序开发标准教程》
这周的任务就是复习上周所学的I/O知识,总结上课讲的进程知识。
我总结了fork函数的具体用法,理解了运行的过程。
这些知识让我不断地深入了解计算机,知其然,知其所以然。
标签:
原文地址:http://www.cnblogs.com/yg137565645/p/4967505.html