文件描述符fd和重定向(dpu、dpu2)

news/2025/2/27 11:32:19

一:文件描述符
文件描述符是什么?
文件描述符实际是一个数字,进程如何通过一个数组来操作文件?
这里写图片描述
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 }                                                                                    

这里写图片描述


http://www.niftyadmin.cn/n/2559810.html

相关文章

Handler的应用场景

如果在一个activity里面有多个线程去更新UI&#xff0c;并且都没有加锁机制&#xff0c;那就会造成更新UI错乱&#xff1b;而如果对更新UI的操作都进行加锁处理&#xff0c;就会造成性能下降。使用消息机制&#xff0c;就不必担心多线程的问题&#xff0c;因为更新UI 的操作&am…

库函数IO和系统调用

C文件I/O相关操作&#xff1a; fopen: FILE *fopen(const char *path, const char *mode); 1 #include<stdio.h>2 #include<errno.h>3 #include<string.h>45 int main()6 {7 FILE *fp;8 fpfopen("./tmp.txt","r"); //…

信号的产生

进程信号&#xff1a; 信号生命周期&#xff1a;信号的产生—>信号的注册—>信号的阻塞&#xff08;屏蔽&#xff09;—>信号的注销—>信号的处理 信号列表&#xff1a;知道有哪些信号&#xff0c;并且对应了哪些操作 kill &#xff1a;可以杀死一个进程&#xff0…

BroadcastReceiver中onReceive()方法中需要注意什么

广播接收者运行在主线程&#xff0c;所以广播接收者的onReceive()方法内不能有耗时的操作&#xff0c;需要放在子线程中做。 onReceive()的生命周期很短&#xff0c;有可能广播接收者结束&#xff0c;子线程还没有结束&#xff0c;这时广播接收者所在的进程有可能被杀掉&#x…

信号的注册、信号的注册

信号的注册&#xff08;修改信号pending位图&#xff09; 信号记录在进程pcb中&#xff1b;信号集合&#xff1a;sigset_t 结构体&#xff08;保存信号&#xff09;&#xff1a;进程记录一个信号时是通过这个结构体的位图来记录的&#xff08;1号信号在位图第0位置存储&#x…

如何实现程序开机自启动

分为三步&#xff1a; 在AndroidManifest.xml文件中定义广播和声明权限实现自定义广播类接收到广播后&#xff0c;设置Activity的启动模式 在AndroidManifest.xml文件中定义广播和声明权限 <uses-permissionandroid:name"android.permission.RECEIVE_BOOT_COMPLETED&…

Android中如何实现定时任务

定时任务有3种方法&#xff0c;参考了原文章 https://www.cnblogs.com/Im-Victor/p/7457027.html 采用Handler与线程的sleep(long )方法&#xff08;不建议使用&#xff0c;Java的实现方式&#xff09;采用Handler的postDelayed(Runnable,long)方法采用Handler与timer及TimerTa…

信号的处理

信号的处理&#xff1a; 每一个信号实际都对应了某个事件&#xff0c;当进程收到了一个信号&#xff0c;那么就意味着现在有一个重要的事件要处理&#xff0c;因此会打断我们当前的操作&#xff0c;然后去处理这个事件。 信号还有一个名字&#xff1a;信号的递达。 那么进程什么…