Linux环境编程--文件描述符的使用以及常用来搭配的几个函数实例
一.文件描述符
对于内核而言,所有打开的文件、设备、网络socket都是通过文件描述符引用,文件描述符是一个非负整数。当打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描述符。当读、写一个文件时,使用open或creat返回的文件描述符表示该文件,将其作为参数床给read或write。
应用程序运行的时候,系统将会为该进程默认打开三个文件描述符:
标准输入:STDIN_FILENO (0)
标准输出:STDOUT_FILENO (1)
标准出错:STDERR_FILENO (2)
文件描述符的变化范围是:0~OPEN_MAX-1 (OPEN_MAX-1这边可以修改)
注:write()是系统调用函数,不需要头文件,1表示标准输出(屏幕)
二.函数open()
int open(const char *path,int oflag,.../*mode_t mode*/);
返回值int fd 文件描述符,open系统调用返回的文件描述一定是最小的未使用的文件描述符值。
注:fd = open("test.log",O_RDWR|O_CREAT|O_TRUNC,0644); //在没有test.log的情况下读写它,并且将内容清除,给予权限644。此时,open返回的最小值就是标准输出
参数说明:
三.函数close()
该函数用来关闭一个打开的文件,关闭一个文件时还会释放该进程在该文件上的所有记录锁。当一个进程终止时,内核自动关闭它所有打开的文件。
int close(int fd);
注:标准输出重定向:
1.close(1); //表示将标准输出到屏幕这条路径关闭(系统默认1指定为屏幕),但是不意味着标准输出被关闭。
四.函数creat()
等价于open(path,O_WRONLY|O_CREAT|O_TRUNC, mode);
五.函数lseek()
每打开一个文件时都有一个与其关联的“当前文件偏移量”。它通常是一个非负整数,用以度量从文件开始处计算的字节数。通常读写操作都是从当前文件偏移量处开始,并使用偏移量增加所读写的字节数。
按系统默认的情况,当打开一个文件时,除非指定O_APPEND选项,否则该偏移量被设置为0.
例子:lseek(fd,0,SEEK_SET);表示从文件开头往后0处读取.
六.函数read()/write()
read()函数用来从打开的文件中读取数据:
ssize_t read(int fd, void *buf, size_t nbytes);
如read成功,则返回读到的字节数。如已到达文件的尾端,则返回0。
write()函数用来往打开的文件中写入数据:
ssize_t write(int fd, const void *buf, size_t nbytes);
如write成功,则返回实际写入的字节数,失败返回-1。
例子:
其输出结果为:
原因:
1.从数据的方向去理解,buf是局部变量在栈中,所以是一个随机值,因此在使用buf之前要用memset(buf,0,sizeof(buf))进行清零。
2.处理后还没有解决,那是因为文件有一个偏移量,buf此时读的是光标处(EOF),二光标处默认在你所写的文字之后,所以还需要设置读取时光标的位置lseek(fd,0,SEEK_SET)表示从开头读取到EOF。还有lseek要放在read之前否则就跟没有设置一样。
总结:
1.每次使用buf时,一定要紧跟memset的设置
2.考虑是否需要修改文件偏移量,一般是读取文件都是需要修改
修改之后的代码:
结果如下:
九.函数dup()\dup2()
以下两个函数都可以用来复制一个现有的文件描述符。
int dup(int fd);
int dup2(int fd, int fd2);
由dup返回的新文件描述符一定是当前可用文件描述符中的最小数值。
dup2可以用fd2参数指定新描述符的值。如果fd2已经打开,则先关闭。如fd等于fd2, 则dup2返回fd2, 而不关闭它。
使用这两个函数可以用来实现标注输入、标准输出、标准出错重定向:
int fd = -1;
fd = open(“std.txt”, O_RDWR|O_CREAT|O_TRUNC, 0666);
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
printf(“Hello Word!\n”);
注:dup2()就等价于之前的先close(1)然后open(fd,..),dup2更方便
十.ioctl()
ioctl()函数一直是I/O操作的杂物箱,不能用本章中其他函数表示的I/O操作通常都能用ioctl()表示。终端I/O、设备I/O是使用ioctl()最多的地方。
int ioctl(int fd, int cmd, ...);
fd: 文件描述符
cmd: 命令字,这个参数需要与设备驱动中的cmd保持一致。
第三个参数可选
例子:
int fd = -1;
fd = open(“/dev/led”, O_RDWR);
ioctl(fd, TURN_OFF, 3);
close(fd);