Linux系统编程_2_文件I/O(系统调用&库函数)

时间:2021-03-31 04:42:09

这里说的的文件I/O指的是不带缓存的;

1.关于带缓存的IO操作和不带缓存的IO操作,参见另一篇文章:

带缓存IO和不带缓存IO详解


Linux中的文件IO(不带缓存的IO)通常用的有以下几个:

open    read    write    lseek   close


2.open的参数

int open(filename, mode);

mode 通常可以是O_RDONLY(只读)  O_WRONLY(只写)  O_RDWR(读写)必须指定且只能指定一个!

其他的可供选择,可通过或运算添加:O_APPEND  O_CREAT  O_EXCL   O_TRUNC


3.read与write在读取网络数据时,可能由于网络的缓冲机制等造成实际读到的数据小于应读数据。

所以,应该做相应的数据完整性判断操作;


4.内核其实也是一个软件,内核的接口叫做系统调用(system call),系统调用是内核提供给应用层使用的,除了应用程序可以调用系统调用外(如shell),库函数也可以调用系统调用。

一个Linux操作系统的体系结构图

Linux系统编程_2_文件I/O(系统调用&库函数)

下面是一些简单的系统调用实例:

A. 使用read,write实现简单的复制功能

#include <stdio.h>
#include <unistd.h>

#define SIZE 1024

int main()
{
int fd;
int n;
char buf[SIZE];

while( (n = read(STDIN_FILENO, buf, SIZE)) > 0 )
{
if( write(STDOUT_FILENO, buf, n) != n )
{
perror("Write error!");
return -1;
}
}
if(n < 0)
{
perror("Read error!");
return -1;
}

return 0;
}

Linux系统中每当运行一个程序时,所有的shell都为其打开3个文件描述符,标准输入STDIN_FILENO、标准输出STDOUT_FILENO、标准错误STDERR_FILENO;

上面的程序,直接运行时,./a.out,在标准输入中输入什么,程序就会显示什么;

运行./a.out < a.c > b.c,则程序会把a.c中的内容拷到b.c中去,为什么?

因为现在的标准输入已经重定向了,变成了a.c文件而不是标准输入in;


B. 用lseek实现获取文件大小的功能:

1 #include <stdio.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4 #include <stdlib.h>
5
6 int main(int argc, char ** argv)
7 {
8 off_t size;
9 int nFd;
10
11 if(argc < 2)
12 {
13 printf("Usage: ./size xxx\n");
14 exit(-1);
15 }
16
17 nFd = open(argv[1], O_RDONLY);
18 if(-1 == nFd)
19 {
20 perror("Open file error");
21 exit(-1);
22 }
23 size = lseek(nFd, 0, SEEK_END);
24 printf("The file size is : %d\n", size);
25
26 return 0;
27 }

5.dup与dup2函数,都用来复制一个现存的文件描述符

    int dup(int fd);

    int dup2(int fd1,int fd2);//若 fd2已经打开,则先关闭


6.sync  fsync  fdatasync函数都可以用来将缓冲区中的数据刷新到物理磁盘

    void sync(void);

    int fsync(int filedes);

    sync函数并不等待实际的写磁盘操作结束后返回。通常称为update的守护进程会周期性的调用sync函数,保证了定期冲洗内核的块缓冲区;

    fsync指定了文件描述符,操作单一的文件,函数等待写磁盘操作结束后返回,可以用于数据库这样的应用程序。


7.fcntl函数——可以改变已经打开的某个文件的性质

#include <fcntl.h>

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

fcntl函数有五种功能:

1.复制一个现有的文件描述符 ( cmd=F_DUPFD )

2.获取/设置文件描述符 ( cmd=F_GETFD / cmd=F_SETFD )

3.获取/设置文件状态 ( cmd=F_GETFL / cmd =F_SETFL )

4.获取/设置异步IO所有权 ( cmd=F_GETOWN / cmd=F_SETOWN) 

5.获取/设置文件记录锁 ( cmd=F_GETLK / cmd=F_SETLK/F_SETLKW )

具体的使用方法后面会做记录。