文件I/O

来源:互联网 发布:电脑系统维护软件 编辑:程序博客网 时间:2024/06/02 03:43

print函数

printf函数的调用链: printf  write  int 0x80  sys_write

printf和write属于用户层函数,int 0x80相当于一闪门,进入到内核函数sys_write。

sys_write 完成后,再一层一层的将结果返回到 printf。

open函数

//包含头文件#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>//函数原型int open(const char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);

1、 flags有3个必选项 O_RDONLY、O_WRONLY、O_RDWR。这三个值是互斥的,只能选一个。

2、flags有很多可选项,O_CREAT、O_APPEND、O_EXCL、O_TRUNC、O_NONBLOCK这些值可以多选。不能和必选项发生冲突。

3、若选择了O_CREAT选项、那么open函数第三个参数mode就必须写。O_EXCL只和O_CREAT配合使用,若开启O_EXCL,而且创建的文件存在,函数返回-1。

4、O_APPEND表示追加的方式打开文件。

5、O_TRUNC表示打开文件将长度截取为0。

6、O_NONBLOCK针对设备文件,比如屏幕网络,表示非阻塞方式打开IO。

flag选项示例:

open('test', O_RDONLY);                     // 只读方式打开open('test', O_WRONLY | O_APPEND);          // 追加的方式打开open('test', O_RDWR);                       // 读写的方式打开open('test', O_WRONLY | O_CREAT, 0666);     // 创建文件,只写,权限是 0666open('test', O_WRONLY | O_TRUNC);           // 只写打开,同时把文件长度截断成 0.

read函数

//头文件#include <unistd.h>//函数原型ssize_t read(int fd, void *buf, size_t count);
返回值:返回读到的字节数,返回0表示读到文件末尾,返回-1表示出错。

write函数

//头文件#include <unistd.h>//函数原型ssize_t write(int fd, const void *buf, size_t count);

返回值  返回写入的字节数,出错返回-1

lseek函数

//头文件#include <sys/types.h>#include <unistd.h>//函数原型off_t lseek(int fd, off_t offset, int whence);

改变文件的当前的偏移量。
当open函数打开一个文件的时候,偏移量默认为0
whence的值: SEEK_SET 文件头部   SEEK_CUR 文件尾部 SEEK_END 文件尾部

阻塞IO

通常情况下,从普通文件传数据,会在有限的时间内返回,如果从设备、网络中读取数据如果没有数据可读read一定会堵塞不会返回。

read的这种行为称为block,一旦发生block进程会被操作系统投入随眠,直到等到事件发生进程才被唤醒。

系统调用write同样有可能被阻塞,比如向网络写入数据,若对方不接收,本端缓冲区一旦写满就会被阻塞。

阻塞IO与非阻塞IO效率


阻塞IO与非阻塞IO的几个问题:

1、阻塞与非阻塞是文件本身的特性,不是系统调用read/write可以控制的。

2、终端默认是阻塞的,我们可以重新open设备文件/dev/tty(表示当前终端),打开时指定O_NONBLOCK标志就行了。

3、非阻塞read,如果有数据到来返回读到的字节数。如果没有数据返回-1。

fcntl函数

//头文件#include <unistd.h>#include <fcntl.h>//函数原型int fcntl(int fd, int cmd, ... /* arg */ );
fcntl函数可以修改文件状态位的标志,fcntl函数第二个参数取不同的值有着不同的功能,如果失败返回-1 。

以上函数使用测试代码

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#include <errno.h>#include <fcntl.h>int main(int argc, char const *argv[]){if (argc != 3){printf("输入参数有误。\n");return 0 ;}int srcfd = open(argv[1],O_RDONLY);//只读方式打开文件perror("open"); if(srcfd == -1){return -1 ;}int dsfd = open(argv[2],O_CREAT | O_WRONLY,0666);perror("open");if (dsfd == -1){return -1 ;}int len = 0 ;char* buff[1024] ;memset(buff,0,sizeof(buff));while(len = read(srcfd,buff,sizeof(buff)) > 0){write(dsfd,buff,sizeof(buff));memset(buff,0,sizeof buff);}lseek(srcfd,-20,SEEK_END);//将文件指针冲文件末尾向文件头部偏移20字节read(srcfd,buff,sizeof buff);write(STDOUT_FILENO,buff,sizeof(buff));close(dsfd);//关闭文件close(srcfd);//阻塞I0实验write(STDOUT_FILENO,"阻塞实验开始\n",sizeof("阻塞实验开始\n"));memset(buff,0,sizeof(buff));read(STDIN_FILENO,buff,sizeof(buff));printf("read : %m\n");write(STDOUT_FILENO,buff,sizeof(buff));write(STDOUT_FILENO,"阻塞实验结束\n",sizeof("阻塞实验结束\n"));write(STDOUT_FILENO,"非阻塞实验开始\n",sizeof("非阻塞实验开始\n"));//非阻塞int fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);printf("open : %m\n");printf("fd = %d\n", fd);int i = 0 ;for (i = 0; i < 10; ++i){len = read(fd, buff, sizeof(buff));printf("len = %d\n",len );    if (len < 0)     {    if (errno == EAGAIN)     {        sleep(1); // 让出 CPU,避免CPU长时间空转      }         else       {        exit(1);      }       }       else     {    write(STDOUT_FILENO,buff,sizeof buff);    memset(buff,0,sizeof buff);    }  }close(fd);printf("非阻塞实验结束\n");printf("fcntl实验\n");fd = open(argv[1],O_RDWR|O_APPEND);perror("open");if(fd < 0){exit(0);}int flags = fcntl(fd,F_GETFL);perror("fcntl");if (flags < 0){exit(-1);}if (flags & O_RDONLY) {printf("O_RDONLY\n");}if (flags & O_WRONLY) {printf("O_WRONLY\n");}if (flags & O_RDWR) {printf("O_RDWR\n");}if (flags & O_NONBLOCK) {printf("O_NONBLOCK\n");}    return 0;}


原创粉丝点击