一:文件描述符
文件描述符是什么?
文件描述符实际是一个数字,进程如何通过一个数组来操作文件?
Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0,标准输出1,错误标准输出2;
0,1,2对应的物理设备一般是:键盘,显示器,显示器。
文件描述符是进程pcb中files _struct这个结构体中文件描述信息的结构体数组的下标,操作系统就可以通过这个数字下标找到对应的文件信息,来完成对这个文件的操作。
其他文件描述符是未使用的最小下标。
//test.c
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<fcntl.h>
4 #include<sys/stat.h>
5 #include<sys/types.h>
6
7 int main()
8 {
9 // close(0);
10 //close(2); //如果将2关闭即错误标准输出,将无法perror
11 close(1);//如果将1标准输出关闭,将无法printf,因为printf是把内容打印到标准输出上
12 // 如果关闭0,1,2对程序没有影响,关闭哪个,下面的fd会输出那个,因为在files_struct数组当中,找到当前没有使用的最小下标,作为新的文件描述符
13 // 如关闭0 ,则fd会输出0
14 int fd=open("tmp.txt",O_RDONLY);
15 if(fd<0) //错误会返回-1
16 {
17 perror("open error");
18 return -1;
19 }
20 printf("fd:%d\n",fd);
21 close(fd);
22 return 0;
23 }
二:重定向
对上面test.c程序,如果是close(1),printf将会把内容写入到tmp.txt:
dup和dup2能对输入文件描述符进行重定向。
dup函数创建一个新的文件描述符,该新的文件描述符和描述符oldfd指向相同的文件、管道或网络连接。并且dup返回的文件描述符取系统可用坐标最小值;dup2是将描述符newfd指向和oldfd相同的文件、管道或网络连接,dup2可以用newfd指定新描述符的数值,如果newfd已经打开,则先将其关闭,如果newfd等于oldfd,则dup2返回newfd,而不关闭它。
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<fcntl.h>
4 #include<string.h>
5
6 //文件描述符是文件描述信息结构体数组的下标;
7 //也就代表文件描述符的分配是有限的
8 //因此打开一个文件一定要关闭,尤其要注意循环打开文件的时候
9 //文件描述符分配规则:每次找最小未使用下标
10
11 int main()
12 {
13 int fd=-1;
14 close(0);//将标准输入关闭,就会分配最小的0下标
15 umask(0);
16 //读写打开,如果不存在,则创建一个文件权限为644,必须前面加上0
17 fd=open("./tmp.txt",O_RDWR|O_CREAT,0664);
18 if(fd<0)
19 {
20 perror("open error");
21 return -1;
22 }
23 printf("fd:%d\n",fd);//因为close(0),所以fd取最小值0
24
25 //复制标准输出1,返回一个新的描述符也指向1所指的标准输出
26 //也就是说向test.fd写入数据实际就是向标准输出写入数据
27 int test_fd=dup(1);
28 printf("test_fd:%d\n",test_fd);
29 write(test_fd,"hello\n",6);
30 // close(test_fd);
31
32 //fd原本指向的文件是./tmp.txt,经过dup2重定向之后
33 //fd指向的文件将更改为test_fd所指向的文件
34 //因为test_fd是拷贝的标准输出
35 //因此向fd写入内容,也将打印到标准输出
36 // 而原本fd如果指向一个文件,这个文件将会被关闭
37 int ret=dup2(test_fd,fd);//返回值为fd描述符
38 printf("ret:%d\n",ret);
39 printf("fd:%d\n",fd);
40 write(fd,"this is test\n",13);
41 close(fd);
42 close(test_fd);
43 return 0;
44 }