unix编程(一)文件I/O

来源:互联网 发布:地方台 直播软件 编辑:程序博客网 时间:2024/05/18 00:05

文件描述符

0,1,2对应STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO三个标准输入,输出,出错


open函数

#include <fcntl.h>

int open(const char* path, int oflag, ...)'

path就是文件名字

oflag参数

首先必须5项选1:O_RDONLY只读  O_RDONLY只写 O_RDWR读写 O_EXEX只执行  O_SEARCH只搜索

下面是可选的:选几个常用的

O_APPEND 每次写时追加到文件尾

O_CREATE 文件不存在的时候创建它

O_SYNC 每次write等待物理I/O操作完成

O_TRUNC 如果文件存在 而且是只写或者读写打开,会清空文件内容


create函数

其实等于

open(path, O_WRONLY|O_CREAT|O_TRUNC,mode);


close函数

只是将打开文件的计数减1,计数为0才会关闭文件。进程终止就会关闭所以其打开的文件。


lseek函数

off_t lseek(int  fd, off_t offset, int whence);

off_t currpos;

currpos = lseek(fd, 0, SEEK_CUR);

如果这个返回-1,代表文件描述符指向一个管道,FIFO,socket等。最好用-1来判断,不要用小于0来判断,因为有的设备返回会有负数。


原子操作

多步组成的一个操作,不会被其他进程打断。

pread,pwrite函数,就是将lseek和write,read组成一个操作。成为原子操作,分开可能会被其他进程打断。


dup dup2函数

这两个函数都是对fd重定向,在另一篇转载的博客有比较详细的说明

dup函数 等效 fcntl_fd, F_DUPFD, 0);

dup2(fd, fd2)等效

close(fd2);

fcntl_fd, F_DUPFD, fd2);

但是dup2是原子操作

下面举个adbd中的dup2函数例子

static int create_subproc_raw(const char *cmd, const char *arg0, const char *arg1, pid_t *pid){    // 0 is parent socket, 1 is child socket    int sv[2];    if (adb_socketpair(sv) < 0) {        printf("[ cannot create socket pair - %s ]\n", strerror(errno));        return -1;    }    *pid = fork();    if (*pid < 0) {        printf("- fork failed: %s -\n", strerror(errno));        adb_close(sv[0]);        adb_close(sv[1]);        return -1;    }    if (*pid == 0) {        adb_close(sv[0]);//子进程关闭0端        init_subproc_child();        dup2(sv[1], STDIN_FILENO);        dup2(sv[1], STDOUT_FILENO);        dup2(sv[1], STDERR_FILENO);        adb_close(sv[1]);//关闭原来的sockpair的1端,无用了。因为有3个标准的fd指向了它        execl(cmd, cmd, arg0, arg1, NULL);        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",                cmd, strerror(errno), errno);        exit(-1);    } else {        adb_close(sv[1]);//父进程关闭1端        return sv[0];    }}
这里主进程创建了一对socketpair,然后fork一个子进程。子进程复制了父进程的文件描述符表。因此这对sockpair被打开了两次。主进程返回了0端,1端

0-> shell  1-> shell  2-> shell   dup2之后  

0-> sockpair 1端  1-> sockpair 1端  2-> sockpair 1端

而原来sockpair1端的fd其实没用了,就可以关闭了。


函数fcntl

int fcntl(int fd , int cmd, ...);

设置fd的属性

常用cmd

F_SETFL 设置文件的状态标志比如 O_SYNC

F_GETFL 获取文件的状态标志

F_DUPFD fd重定向

F_SETFD 设置fd标志,比如FD_CLOEXEC代表不能使用excel开启这个fd



1 0