Linux文件所用到的系统调用的函数总结

首先说一下文件描述符,一个进程打开一个文件,其实都是通过文件描述和文件指针进行引用的,其结构好像一个键值对,键对应的就是文件描述符,文件描述符是一个非负整数。值就是对应的文件指针,文件指针指向的就是文件表项,其中文件表项就是好比C语言的一个结构体,其中包括文件的读写状态,文件的偏移量,v节点。其中v节点是所有文件系统中i节点的公共部分。我这边没有画图工具,这两天弄个画图工具把这部分补充一下,做一个图。下边对文件部分的函数做一个大致的介绍:

1. 打开和创建文件,需要包含的头文件和函数名如下:

    #include <fcntl.h>

    int open(const char *path, int flag, mode_t mode);

    其中第三个参数是可有可无的,打开文件的时候不需要第三个参数,只有创建文件的时候需要第三个参数,举例如下:

    1)、打开文件:

    int fd = open("file.txt", O_RDONLY);//以只读的方式打开文件

    2)、打开文件,如果文件不存在就创建文件

    #define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)

    int fd = open("file.txt", O_RDONLY|O_CREAT,  RWRWRW);//如果文件存在,以只读的方式打开,如果不存在则先创建一个具有rw-rw-rw-权限的文件(还与umask有关,我们后边会说到),然后以只读的方式打开,返回文件的文件描述符。

    现在的系统都有/dev/fd目录,其中目录项的名字为0、1、2等文件,打开/dev/fd/n等效于复制描述符n(假定n是打开的)。如 int fd = open("/dev/fd/0", mode);//打开标准输入

2. 创建文件

    #include <fcntl.h>

    int creat(const char *path, mode_t mode);

    这个函数完全可以用open来替代,此函数等效于

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

    但是考虑到历史的原因还是有这个函数,这个函数的的不足之处是它是以只写的方式打开所创建的文件。如果要打开一个文件,先写后读的话,必须要经过creat, close, open三个函数才可以。如果直接用open创建一个文件并进行读写的话可以用一个函数直接表示:open(path, O_RDWR|O_CREAT|O_TRUNC, mode);

    创建文件举例:

    #define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)

    int fd = creat("file.txt", RWRWRW);

3. 关闭一个打开的文件

    #include <unistd.h>

    int close(int fd);//关闭一个打开的文件.

4. 为一个打开文件设置偏移量

    #include <unistd.h>

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

为描述符为fd的打开文件设置偏移量,其中off_t你可以把它想象成为一个int型就OK,表示相对于whence的多少个字节的偏移量,whenceSEEK_SET, SEEK_CUR, SEEK_END分别代表相对于文件的开始,当前偏移,文件的结尾。当然offset可以为负数。成功返回新的文件偏移量,失败返回-1。举例如下:

    off_t currpos = lseek(fd, -10, SEEK_CUR);//将该文件的指针偏移量向左移动10个字节。

如果文件描述符指向的是一个管道、FIFO或者套接字的话返回-1.不能设置其偏移量。

    注意:如果文件偏移量大于当前文件长度的话文件会产生空洞,空洞是不会再磁盘上占用扇区的。但是如果你用cp命令复制一个带有空洞的文件的话,复制的文件会把空洞填为0,这时候就会占用磁盘扇区。具体占用几个扇区可以用ll命令来查询。

5. 读文件

    #include <unistd.h>

    ssize_t read(int fd, void *buf, size_t nbytes);

其中成功返回读取到的字节数,失败返回-1, ssize_t可以看做int, size_t可以看做unsigned short类型。将读取到的数据保存到buf中, nbytes是要求读取的字节数。nbytes和返回的读取到的字节数不一定相等,比如在达到文件末尾的时候刚好剩余10个字节,但是nbytes为30的话,就会返回10,下一次再读取的话返回0,表示已经到了文件的结尾,举例和写文件放在了一起。

6. 写文件

    #include <unistd.h>

    ssize_t write(int fd, void *buf, size_t nbytes);

和read不一样的是其返回值和nbytes要相同,如果不同的话则表示出错返回-1.举例如下,先读后写。

    int n;

    char buf[4096];

    while ( (n = read("file.txt", buf, 4096)) > 0 ){

     if(write(STDOUT_FILENO, buf, n) != n){

     fprintf(stderr, "ERROR: %s\n", "write error!");

     exit(EXIT_FAILURE);

     }

    }

    if( n < 0 )

     fprintf(stderr, "ERROR: %s\n", "read error!");

7. 复制一个现有的描述符

    #include <unistd.h>

    int dup(int fd);

    int dup2(int fd, int fd2);

两个函数都是复制一个现有的描述符,成功则返回新的文件描述符,失败返回-1.

两个函数的区别是dup2可以指定一个文件描述符的值,dup是返回当前可用描述符的最小值。对于dup2,如果fd2已经打开,则先将其关闭,如果fd2等于fd,则返回fd,而不关闭fd2。如果用这两个函数的话,会造成两个文件描述符指向同一个文件表项。举例如下:

    int newfd1 = dup(1);//复制文件描述符为1的文件描述符。

    int newfd2 = dup2(1, 3);//复制文件描述符为1的文件描述符,并指定复制的描述符为3.

8. 改变已经打开的文件的属性

    #include <fcntl.h>

    int fcntl(int fd, int cmd, int argv);//这个函数我们放到后边的来说.

9. stat函数

    #include <sys/stat.h>

    int stat(const char* restrict pathname, struct stat* restrict buf);

    int fstat(int fd, struct stat *buf);

    int lstat(const char* restrict pathname, struct stat* restrict buf);

    int fstatat(int fd, const char* restrict pathname, struct stat* restrict buf, int flag);

    由于时间原因,我明天晚上接着写...


    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值