我的理想是:“让我的家人生活得更好”
6、几个io系统调用
都在 fcntl.h中
fcntl.h sys/types.h
open(char * path, oflag, …/*mode_t mode*/)
第一个参数是文件的名字 最长不要超过MAX_NAME
第二个参数是打开文件参数
第三个是创建文件时候提供的umask
第二个参数一般使用:
O_RDONLY 只读的方式打开
O_WRONLY 只写的方式打开
O_RDWR 读写方式打开
O_CREAT 如果文件不存在则创建一个文件,如果文件存在,返回-1
O_EXCL 如果设置了参数O_CREAT ,如果文件不存在,则创建文件的操作为原子操作
O_TRUNC 如果文件存在则把文件长度设置为0
O_SYN 当进行写操作时候,需要完成物理写操作后,再返回
O_NOBLOCK 如果是打开一个fifo文件,一个块特殊文件,一个字符文件,此次操作和后续的io为非阻塞方式。
Open的每次打开一个文件返回的都是当前最小的可用的文件描述符
fcntl.h sys/types.h
int lseek(int fid, off_t offset, int where)
返回新的文件位移 出错返回-1
第一个参数是问价描述符
第二个参数是一个 偏移量,第三个参数是参考点
对于第三个参数
SEEK_SET 把偏移到距离文件开头offset处
SEEK_CUR 把距离当前的偏移量offset
SEEK_END 偏移量为文件长度+ offset
如果文件偏移量大于文件长度,中间会形成一个空洞,空洞会被设置为/0
可以使用 pos = lessk(fid, 0 ,SEEK_CUR);来判断一个文件是否支持偏移量
#include<fcntl.h>
#include<stdio.h>
#include<unistd.h>
int main()
{
int pos = -1;
if((pos = lseek(STDIN_FILENO,0,SEEK_CUR)) == -1)
printf("can't seek/n");
else printf("can seek/n");
}
root@white-desktop:/home/junjun/apue/chapter3# ./lseekTest.out < lseekTest.c
can seek
unistd.h:
ssize_t read(int fd, void * buf, size_t nbytes)
read成功 返回读到的字节数,如果达到文件结尾则会返回0 错误返回-1
每读一侧 文件偏移量会想后移动读到的字节数。
Unistd.h
ssize_t write(int fd, void * buf, size_t nbytes)
向文件描述符为fd的文件写入nbytes个字节,返回写入的字节数。如果
返回的字节数小于nbytes则出错。在每一次成功写入后,文件偏移量向前移动实际写入的字节数。如果设置了O_APPEND,每次操作之前将文件的偏移量设置为结尾。
7、文件的共享,不同程序之间打开同一个文件。
三层结构:
文件描述符表 -- > 文件表项 -- > v节点
1、每一个进程都有一个文件描述符表,每一个表项有对应的文件描述符,和指向文件表的指针。
2、文件表包含了当前的文件偏移,文件状态标志(读写,同步,阻塞等)
和指向v节点的指针。
3、V节点(V是virtual file system 的头个字母),虚拟文件系统是为了一个系统有多个文件系统的情况下使用,v节点中包含了指向i节点的指针,文件的拥有者,文件大小,已经在磁盘的位置信息等都放在v节点中。
8 、dup
复制文件描述符
int dup(int fd)
复制文件描述符,返回能够使用的最小的文件描述符。否则返回-1.
例如:
fd1 = dup(fd2);
fd1和fd2指向同一个文件表,也就是有相同的文件状态标示。相同的文件偏移量。fork后父子进程都有相同的文件描述符表,都指向相同的文件表。
Int dup2(int fd1, int fd2);
返回新的文件描述符,fd2指向fd1指向的文件描述符。如果fd2已经打开则关闭fd2.
9,fcntl
int fcntl(int filde, int cmd, ……);
改变打开文件的性质。
用得比较多的是:取得和修改文件描述符标志:F_SETFD, F_GETFD
例如
#include<fcntl.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc , char * argv[])
{
int val, val1 = 0;
int fd = open("testfcntl.txt",O_RDONLY|O_APPEND|O_SYNC);
if((val1 = fcntl(fd,F_GETFL,0)) < 0)
{
perror("error");
return -1;
}
printf("fd = %d /n",fd);
val = val1 & O_ACCMODE;
if(val == O_RDONLY) printf("rdonly ");
else if(val == O_WRONLY) printf("wronly " );
else if(val == O_RDWR) printf("rdwr ");
else printf("unknow mode ");
if(val1 & O_APPEND) printf(",append");
#if defined(O_SYNC)
if(val1 & O_SYNC) printf(",syn");
#endif
printf("/n");
close(fd);
}
white@white-desktop:/home/junjun/apue/chapter3$ ./a.out
fd = 3
rdonly ,append,syn
注意 O_REONLY O_REDWR O_WRONLY 是互斥的,必须与O_ACCMODE屏蔽字相与得到读写状态
可以使用 fcntl(fd, F_SETFL, val),来设置文件描述符状态。