《unix环境高级编程》笔记1

第二章 文件I/O

1、文件描述符
  对于内核而言,所有打开的文件都通过文件描述符引用,文件描述符是一个非负整数。

  使用open或者creat返回文件描述符,让read或write使用
  Unix shell使用文件描述符0表示标准输入,1表示标准输出,2表示标准出错输出,为了避免在代码中出现魔数,在<unixtd.h>头文件中,1,2,3替换为符号常量STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO,文件描述符的变化范围是0~OPEN_MAX。


2、open函数
原型:#include<fcntl.h>
    int open(const char *pathname, int oflag, ...)   /*仅当创建新文件时才使用第三个参数*/
 pathname是要打开或创建的文件名字,oflag是参数选项,可选值有:O_RDONLY(只读打开,0),O_WRONLY(只写打开,1),O_RDWR(读写打开,2),这些常量定义在<fcntl.h>头文件中,这3个常量必须指定一个且只能指定一个。下列常量是可选的,O_APPEND(写时追加尾部),O_CREAT(若不存在则创建,需指定第三个参数说明文件访问权限),O_EXCL(若和O_CREAT一起使用,当要创建的文件已经存在就会失败),O_TRUNC(文件截短为0,需文件存在,且为只写或读写打开),O_NOCTTY(pathname指向终端设备,不将它作为控制终端),O_NONBLOCK(pathname指向FIFO、块或字符特殊文件时,设置非阻塞模式)、O_DSYNC(使每次write等待物理IO操作完成,不包括文件属性IO的更新),O_RSYNC(读操作等待写操作完成)、O_SYNC(每次write等待物理IO操作完成,包括文件属性IO的更新)     注意:Linux将O_DSYNC、O_RSYNC、O_SYNC等同与O_SYNC(其实这些知识点应该是自己做实验发现,而不是等着书本来教你~~)     返回最小的未使用描述符数值。


3、creat函数
原型:#include<fcntl.h>
    int create(const char* pathname, mode_t mode);等效于open(pathname, O_WRONLY|O_CREAT|O_TRUNC, mode),可以完全用open函数取代creat函数


4、close函数
原型:#include<unistd.h>
    int close(int filedes);关闭一个文件时还会释放该进程加在该文件上的记录锁。


5、lseek函数
作用:显示的为一个文件设置偏移量,当打开一个文件时,除非设置了O_APPNEND选项,否则文件偏移量都是0

原型:#include<unistd.h>
     off_t lseek(int fileds, off_t offset, int whence);
对offset的解释与whence的值有关,当whence为SEEK_SET,则该文件的偏移量为距文件开头处offset字节处; 当whence为SEEK_CUR,则该文件的偏移量为当前值加上offset,offset可以为正或负;  当whence为SEEK_END,则文件偏移量为文件长度加offset,offset可以为正或负。      返回新的文件偏移量。

     通常,文件的当前偏移量为非负值。但是有的设备允许它为负值。所以在测试lseek返回值时,不要测试它是否小于0,而应该测试是否等于-1


应用:

1、确定打开文件当前偏移量:off_t currpos;       currpos = lseek(fd, 0, SEEK_CUR);
2、确定所涉及的文件是否可以设置偏移量。如果文件描述符引用的是一个管道、FIFO或网络套接字,则lseek返回-1,并将errno设置为ESPIPE。
3、lseek允许定位到文件长度之后,下一次读写绘这样就会造成文件空洞,新写的部分需要分配新磁盘块,空洞部分则不会信分配磁盘块。使用od(1)命令可以观察文件的实际内容。


6、read函数
原型:#include<unistd.h>
     ssize_t read(int filedes, void *buf, size_t nbytes);   成功返回读到的字节数,到文件尾返回0,失败返回-1

有几种情况使得实际读取到的值小于传入的参数值:

1.读到文件末尾时,只会返回到达末尾的长度,再读就会返回0

2.从终端一般只能读一行

3.网络上读


7、write函数
原型:#include<unistd.h>
     ssize write(int filedes, const void* buf, size_t nbytes);   成功返回已写字节数,若出错返回-1


8、关于文件共享
内核使用3种数据结构表示打开的文件:(1)每个进程都有一个打开文件描述符表;(2)内核为所有打开文件维持一张文件表(每个表项包括文件状态标志,当前文件偏移量,指向该节点v节点指针),(3)一个v节点结构包括文件类型及i节点信息(如文件所有者、文件长度、文件所在设备等等)注:linux没有v节点,使用的就是i节点

《unix环境高级编程》笔记1_第1张图片



《unix环境高级编程》笔记1_第2张图片

《unix环境高级编程》笔记1_第3张图片



9、使用原子操作的场合:1)、lseek+write -> 使用O_APPEND标志 或 使用pread函数和pwrite函数


12、fcntl函数:可以改变已打开文件的性质。
原型:#include<fcntl.h>        

int fcntl(int filedes, int cmd, ...)     出错返回-1

功能:(1)、复制现有文件描述符(cmd=F_DUPFD)    (2)、获得设置文件描述符标志(cmd=F_GETFD或cmd=F_SETFD)  (3)、获得或设置文件状态标志(cmd=F_GETFL或cmd=F_SETFL)   (4)、获得设置异步IO所有权(cmd=F_GETOWN或F_SETOWN)   (5)、获得设置记录锁(cmd=F_GETLK、F_SETLK、F_SETLKW)
注意:dup(filedes);等价于fcntl(filedes, F_DUPFD, 0);         dup2(filedes1, filedes2);等价于close(filedes2);    fcntl(filedes1, F_DUPFD, filedes2);


13、ioctl函数:是IO操作的杂物箱,不能用本章中其他函数表示的IO操作通常都能用ioctl表示。
原型:#include<unistd.h>   #include<sys/ioctl.h>     #include<stropts.h>
int  ioctl(int filedes, int request, ...)         若出错,返回-1

每个设备驱动程序都可以为它自己定义一组ioctl命令。系统则为不同种类的设备提供了通用的ioctl命令



14、/dev/fd:该目录下为Linux打开文件描述符的映射。






你可能感兴趣的:(编程,linux,IO,unix,cmd,终端)