LINUX下通过系统调用的文件操作

来源:互联网 发布:龙泉驾校网络授课 编辑:程序博客网 时间:2024/06/07 13:41

相比较标准库函数(fopen、fread、fwrite…)的方式,系统调用的方式只能在类Unix系统下使用,而且,使用系统调用是不带缓冲机制的。

一、缓冲机制:

①.完全缓冲:只有数据超过缓冲区大小时才进行真正的读写操作,比如fread,fwrite函数就是完全缓冲。正常情况下指定读多少字节就读多少字节;

②.行缓冲:当数据为换行符的时候进行一次真正的读写操作,比如标准IO就是行缓冲,一般涉及到终端就是行缓冲的形式;

③.无缓冲:即不对字符进行缓存操作,标准错误输出和系统调用的读写函数就是无缓冲的。

从描述可以看出来,无缓冲一般是比较紧急的,但是因为IO速度比CPU实际运行速度慢,效率会比较低。完全缓冲读满后一次性操作,效率就高了, 但是在缓冲区还有数据分时候程序直接停止就可能导致缓冲区内的数据丢失。


二、文件操作

系统调用是对文件描述符(int类型)进行操作的(相对应的是标准库函数是对文件指针(FILE*)进行操作的)

1.打开文件:

当程序运行时,会有三个文件是默认打开的,分别是:标准输入(0)、标准输出(1)、标准错误输出(2)

Linux下一个进程默认最多可打开1024个文件,实际上由于Linux把其他设备也当成文件,比如管道、套接字的描述符也会占用文件描述符。不用的文件就要及时关掉。

open函数:int open(const char* pathname, int flags);

     int open(const char* pathname, int flages, mode_t mode);

其中path:文件的路径以及文件名

flags取值:O_RDONLY(只读)或O_WRONLY(只写)或O_RDWR(可读可写) 也可以对这几个值进行位或表示增加这几个选项

O_CREAT(文件不存在则创建)O_EXCL(文件存在则出错)O_TRUNC(文件存在则清空该文件)O_APPEND(写数据追加到文件尾)O_NONBLOCK(非阻塞)

mode创建文件时选择文件权限,和chmod的选项一样。

函数返回值为文件描述符。

2.创建文件:

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

3.关闭文件:

int close(int fd);

4.读取文件:

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

fd:文件描述符,buf缓冲区指针,count读取的字节数;返回值为读取到的字节数

5.写入文件:

ssize_t write(itn fd,void* buf, size_t count);

参数设置与返回值和读取函数类似

6.文件定位:

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

fd:文件描述符,offset:偏移的字节数,可为负,whence:SEEK_SET(文件开头)SEEK_CUR(当前位置)SEEK_END(文件结尾)

函数功能:将当前位置从whence移动offset个字节,返回值是新的文件偏移量

可以移到文件结尾后面去,然后在再写入数据,就会在原文件结尾处和写入数据处形成一个数据为0的“空洞”

也可以将位置移到文件尾,根据返回值得到该文件的大小。

7.复制文件描述符:

①:进程中有一个进程文件表通过记录文件描述符记录当前进程打开了哪些文件;文件描述符在内核中对应一个内核文件表,记录了当前位置等信息;内核文件表指向i结构表,i结构表记录了文件的长度、所有者、在硬盘的位置等信息。

②:同一个进程中不同的文件描述符指向不同的内核文件表;


不同进程中如两个文件描述符指向同一个文件则它们各自指向了自己的内核文件表,内核文件表指向了同一个i结构表;



复制文件描述符可以让两个文件描述符指向同一个内核文件;


函数:int dup(int oldfd); 传入旧文件描述符,返回新文件描述符

   int dup2(int oldfd, int newfd); 传入旧文件描述符和指定的新文件描述符

由以上图片可以知道,复制后的文件描述符和旧文件描述符实际上指的是同一个内核文件表,就是说当文件变化时两个文件描述符指向的内核都即时的发生了变化,即他们共享了文件位置等信息。

三、目录操作:

1.删除文件:

int unlink(const char *pathname); 删除pathname

目录下的文件其实就是该目录下有指针指向了文件在磁盘中的位置,删除文件就是讲指向该文件的链表结点删除。

2.读取目录:

①.打开目录:DIR* opendir(const char* name);

返回值是一个指向dir结构体的指针,用于读取目录数据。失败返回NULL

②.读取目录下的文件:struct dirent* readdir(DIR* dirp)

返回一个目录项的信息,包括文件的inode节点号和文件名,目录指针指向下一个目录项;

③:关闭目录:int close(DIR* dirp);

四、如何获取当前文件的文件名、行号等信息。(非系统调用)

编译器有几个内置的宏可以比较方便的得到当前的文件信息;

比较重要的就是文件名:__FILE__;

   行号:__LINE__;

还有几个在这个链接里有说明:如何获取当前文件信息

0 0
原创粉丝点击