fork exec时打开文件的变化
在分析linux系统调用fork,linux系统调用execve时,已经知道:
1.fork时,子进程会复制父进程的打开文件描述符表
2.exec时,进程的打开文件描述符表保持不变
用以下代码观察fork,exec打开文件的变化情况:
父进程fork子进程,睡眠一定时间(方便命令行查看打开文件);
子进程fork孙进程,睡眠一定时间;
孙进程exec新程序,新程序也睡眠一定时间
/* openfiles.c */
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4 #include <errno.h>
5
6 #define BUFSIZE 50
7 #define error() \
8 do { \
9 char buf[BUFSIZE]; \
10 snprintf(buf, BUFSIZE, "[%s][%d][%d]\n", __FILE__, __LINE__, errno); \
11 perror(buf); \
12 } while(0);
13
14 int main(int argc, char *argv[])
15 {
16 int pid, fd;
17 int nsecs;
18 char snsecs[20] = {0};
19 int err;
20 if (argc != 2) {
21 printf("command format: %s sleeptime\n", argv[0]);
22 return -1;
23 }
24
25 nsecs = atoi(argv[1]);
26 if (nsecs < 0 || nsecs > 120) {
27 nsecs = 120;
28 }
29 sprintf(snsecs, "%d", nsecs);
30
31 fd = open(argv[0], O_RDONLY);
32 pid = fork();
22 return -1;
23 }
24
25 nsecs = atoi(argv[1]);
26 if (nsecs < 0 || nsecs > 120) {
27 nsecs = 120;
28 }
29 sprintf(snsecs, "%d", nsecs);
30
31 fd = open(argv[0], O_RDONLY);
32 pid = fork();
33 if (pid == 0) {
34 pid = fork();
35 if(pid == 0) {
36 err = execl("./exec_openfiles", "exec_openfiles", snsecs, (char *) 0);
37 if (err) {
38 error();
39 return -1;
40 }
41 } else if (pid < 0) {
42 error();
43 return -1;
44 }
45 } else if (pid < 0) {
46 error();
47 return -1;
48 }
49
50 sleep(nsecs);
51 close(fd);
52 return 0;
53 }
/* exec_openfiles.c */
1 #include <stdio.h>
2 #include <fcntl.h>
3
4 int main(int argc, char* argv[])
5 {
6 int fd;
7 int nsecs;
8
9 if (argc != 2) {
10 printf("command format: %s sleeptime \n", argv[0]);
11 return -1;
12 }
13
14 nsecs = atoi(argv[1]);
15 if (nsecs <= 0 || nsecs > 120) {
16 nsecs = 120;
17 }
18
19 fd = open(argv[0], O_RDONLY);
20 sleep(nsecs);
21 close(fd);
22 return 0;
23 }
/* Makefile */
1 all:
2 gcc openfiles.c -o openfiles
3 gcc exec_openfiles.c -o exec_openfiles
用以下命令观察三个进程打开文件的变化情况:
查看当前终端并运行openfiles:
[redhat@localhost fork_exec_openfiles]$ tty
/dev/pts/6
[redhat@localhost fork_exec_openfiles]$ ./openfiles 90
通过终端查看刚才运行的进程:
[redhat@localhost fork_exec_openfiles]$ ps -t pts/6 -f
UID PID PPID C STIME TTY TIME CMD
redhat 8165 13780 0 13:20 pts/6 00:00:00 ./openfiles 90
redhat 8166 8165 0 13:20 pts/6 00:00:00 ./openfiles 90
redhat 8167 8166 0 13:20 pts/6 00:00:00 exec_openfiles 90
redhat 13780 2851 0 Jun29 pts/6 00:00:00 bash
通过lsof命令观察以上进程打开的文件:
[redhat@localhost fork_exec_openfiles]$ lsof -p 8165
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
openfiles 8165 redhat cwd DIR 253,0 4096 1068237 /home/redhat/code/syscall/fork_exec_openfiles
openfiles 8165 redhat rtd DIR 253,0 4096 2 /
openfiles 8165 redhat txt REG 253,0 6245 1068231 /home/redhat/code/syscall/fork_exec_openfiles/openfiles
openfiles 8165 redhat mem REG 253,0 141536 134697 /lib/ld-2.12.so
openfiles 8165 redhat mem REG 253,0 1880776 134698 /lib/libc-2.12.so
openfiles 8165 redhat 0u CHR 136,6 0t0 9 /dev/pts/6
openfiles 8165 redhat 1u CHR 136,6 0t0 9 /dev/pts/6
openfiles 8165 redhat 2u CHR 136,6 0t0 9 /dev/pts/6
openfiles 8165 redhat 3r REG 253,0 6245 1068231 /home/redhat/code/syscall/fork_exec_openfiles/openfiles
[redhat@localhost fork_exec_openfiles]$ lsof -p 8166
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
openfiles 8166 redhat cwd DIR 253,0 4096 1068237 /home/redhat/code/syscall/fork_exec_openfiles
openfiles 8166 redhat rtd DIR 253,0 4096 2 /
openfiles 8166 redhat txt REG 253,0 6245 1068231 /home/redhat/code/syscall/fork_exec_openfiles/openfiles
openfiles 8166 redhat mem REG 253,0 141536 134697 /lib/ld-2.12.so
openfiles 8166 redhat mem REG 253,0 1880776 134698 /lib/libc-2.12.so
openfiles 8166 redhat 0u CHR 136,6 0t0 9 /dev/pts/6
openfiles 8166 redhat 1u CHR 136,6 0t0 9 /dev/pts/6
openfiles 8166 redhat 2u CHR 136,6 0t0 9 /dev/pts/6
openfiles 8166 redhat 3r REG 253,0 6245 1068231 /home/redhat/code/syscall/fork_exec_openfiles/openfiles
openfiles 8166 redhat 4r REG 253,0 6245 1068231 /home/redhat/code/syscall/fork_exec_openfiles/openfiles
[redhat@localhost fork_exec_openfiles]$ lsof -p 8167
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
exec_open 8167 redhat cwd DIR 253,0 4096 1068237 /home/redhat/code/syscall/fork_exec_openfiles
exec_open 8167 redhat rtd DIR 253,0 4096 2 /
exec_open 8167 redhat txt REG 253,0 5184 1068238 /home/redhat/code/syscall/fork_exec_openfiles/exec_openfiles
exec_open 8167 redhat mem REG 253,0 141536 134697 /lib/ld-2.12.so
exec_open 8167 redhat mem REG 253,0 1880776 134698 /lib/libc-2.12.so
exec_open 8167 redhat 0u CHR 136,6 0t0 9 /dev/pts/6
exec_open 8167 redhat 1u CHR 136,6 0t0 9 /dev/pts/6
exec_open 8167 redhat 2u CHR 136,6 0t0 9 /dev/pts/6
exec_open 8167 redhat 3r REG 253,0 6245 1068231 /home/redhat/code/syscall/fork_exec_openfiles/openfiles
exec_open 8167 redhat 4r REG 253,0 5184 1068238 /home/redhat/code/syscall/fork_exec_openfiles/exec_openfiles
注:
cwd:当前目录
rtd:根目录
txt:程序代码段(可看出exec后的代码段不同)
mem:映射到进程地址空间的动态库
0u,1u,2u:标准输入(对应当前的虚拟终端),标准输出,标准错误
3r,4r:打开的文件
内核导出到proc文件系统中的进程打开文件信息:
[redhat@localhost fork_exec_openfiles]$ ll /proc/8165/fd
总用量 0
lrwx------. 1 redhat redhat 64 6月 30 13:45 0 -> /dev/pts/6
lrwx------. 1 redhat redhat 64 6月 30 13:45 1 -> /dev/pts/6
lrwx------. 1 redhat redhat 64 6月 30 13:45 2 -> /dev/pts/6
lr-x------. 1 redhat redhat 64 6月 30 13:45 3 -> /home/redhat/code/syscall/fork_exec_openfiles/openfiles
[redhat@localhost fork_exec_openfiles]$ ll /proc/8166/fd
总用量 0
lrwx------. 1 redhat redhat 64 6月 30 13:45 0 -> /dev/pts/6
lrwx------. 1 redhat redhat 64 6月 30 13:45 1 -> /dev/pts/6
lrwx------. 1 redhat redhat 64 6月 30 13:45 2 -> /dev/pts/6
lr-x------. 1 redhat redhat 64 6月 30 13:45 3 -> /home/redhat/code/syscall/fork_exec_openfiles/openfiles
lr-x------. 1 redhat redhat 64 6月 30 13:45 4 -> /home/redhat/code/syscall/fork_exec_openfiles/openfiles
[redhat@localhost fork_exec_openfiles]$ ll /proc/8167/fd
总用量 0
lrwx------. 1 redhat redhat 64 6月 30 13:45 0 -> /dev/pts/6
lrwx------. 1 redhat redhat 64 6月 30 13:45 1 -> /dev/pts/6
lrwx------. 1 redhat redhat 64 6月 30 13:45 2 -> /dev/pts/6
lr-x------. 1 redhat redhat 64 6月 30 13:45 3 -> /home/redhat/code/syscall/fork_exec_openfiles/openfiles
lr-x------. 1 redhat redhat 64 6月 30 13:45 4 -> /home/redhat/code/syscall/fork_exec_openfiles/exec_openfiles
父进程:8165
fork的子进程:8166
exec的孙进程:8167
由以上数据可以看出:
1.对比父进程与子进程打开的文件,可知fork后子进程会保持父进程打开的文件不变;父子进程打开的文件在fork之后会相互独立,如上例的子进程新打开的文件4不会出现在父进程打开文件表中。
2.对比子进程与孙进程打开的文件,可知exec后孙进程会保持子进程打开的文件不变(注意子进程文件4是在exec之后打开的);子孙进程打开的文件在exec之后相互独立,如上例的子进程打开的文件4不会出现在孙进程中,孙进程打开的文件4不会出现在子进程中。
所以可以通过打开的文件描述符实现父子进程的通信。
如以下命令
[redhat@localhost fork_exec_openfiles]$ ps -o pid,ppid,comm | cat
PID PPID COMMAND
8771 13780 ps
8772 13780 cat
13780 2851 bash
就用到了管道和打开文件描述符表来实现通信:
1.shell创建一个管道,并fork两个进程,8771和8772
2.将进程8771的标准输出dup2到管道的写端(如有必要dup2会自动关闭标准输出),然后exec装入ps镜像,ps开始执行,输出写到管道中
3.将进程8772的标准输入dup2到管道的读端(如有必要dup2会自动关闭标准输入),然后exec装入cat镜像,cat开始执行,从管道中读数据
由于fork与exec过程中,打开文件描述符表都不变,所以可以通过以上步骤来实现进程间管道通信。
fork exec时打开文件的变化相关推荐
- Unity中打开文件窗口(OpenFileDialog)的几种方法对比
1 概述 本文链接:http://blog.csdn.net/ithot/article/details/76997237 用Unity以来,一直都没怎么关注过打开对话框去选取本地文件,最近需要用到这 ...
- Java打开文件夹/文件
Java执行本地命令,可以用Runtime实现,也可以用ProcessBuilder实现.无论使用哪种方式,必须要给正确的执行命令,例如打开文件夹的命令是explorer.exe,打开txt文件not ...
- 【解决】Word 在试图打开文件时遇到错误 请尝试下列方法:* xxx * xxx * xxx
[解决]Word 在试图打开文件时遇到错误 请尝试下列方法:* xxx * xxx * xxx 参考文章: (1)[解决]Word 在试图打开文件时遇到错误 请尝试下列方法:* xxx * xxx * ...
- c语言打开文件出现分段故障,我不明白为什么我使用ifstream时出现分段错误
我对C++相当陌生.我试图打开一个文件并将其传递给另一个方法,以便我可以从ifstream读取数据.这是打开文件的方法.我不明白为什么我使用ifstream时出现分段错误 int main() { / ...
- python使用open打开文件时显示文件不存在-Python打开文件open()的注意事项
刚刚用open(fileName)来打开txt格式的文件,总是出现错误,总是找不到文件读取的内容,后来才发现是open()在使用过程中自动关闭了.这里介绍另种方法解决这个问题. 第一种方法. with ...
- php怎么关联默认打开程序,win10系统打开文件时提示“请在默认程序控制面板中创建关联”如何解决...
近日有win10系统用户反映说在打开文件的时候,突然遇到了"请在默认程序控制面板中创建关联"的提示,导致无法打开文件,这该怎么办呢,本教程就给大家带来win10系统打开文件时提示& ...
- java 对第三方的异常_Java第三方API调用打开文件方法时抛出异常
想用Java写一个音乐播放器,使用了Javazoom里的第三方API,调用打开文件的方法open(File file)时,抛出了IOException:Resetting to invalid mar ...
- 打开excel文件并写入_双击Excel表格文件时只打开程序不能直接打开文件
故障描述:双击EXCEL表格文件时仅打开了excel窗口,对应文件不能直接打开文件 ,需通过文件--打开--选中文件来打开. 打开excel后不显示文件内容 注意事项:遇到此类问题时首先通过" ...
- python打开方式错误_浅谈python 调用open()打开文件时路径出错的原因
昨晚搞鼓了一下python的open()打开文件 代码如下 def main(): infile =open("C:\Users\Spirit\Desktop\bc.txt",'r ...
最新文章
- c语言分段错误空指针,C语言空指针总结 - 祂的小哥哥的个人空间 - OSCHINA - 中文开源技术交流社区...
- RMB77元实现全身VR跟踪,来自配合微软Kinect的Driver4VR
- 改进合作 Git 工作流:自动提取、合并提交
- java wifimanager_Java WifiManager.disableNetwork方法代碼示例
- ZOJ 3965 Binary Tree Restoring
- 牛刀小试、用SharePoint 实现请假管理功能
- oracle错误27101,ORA-27101ORA-01034错误解决
- Python冒泡排序(4)
- 无废话ADO.NET 第三章 进行查询
- 取代上万行遗留代码,机器学习模型终“上位”
- 苹果手机型号对应表及尺寸
- E-Prime1.1安装教程及软件下载
- 关于appium环境搭建
- 开源跨平台2D游戏引擎Love2D介绍
- 获取本地外网ip的api接口
- Win10无法访问共享文件,错误代码0x80004005
- 程序员代码规范——马化腾、刘强东写的代码,你见过吗
- php 发邮件 上传附件,PHPMailer实现PHP的邮件发送,附带附件
- 计算机专业学英语建模,英语翻译段子如下:三维建模技术主要的方法就是利用计算机三维制作软件进行三维基础建模,这主要包括多边形建模方式建模、NUR...
- (实测可用)STM32CubeMX教程-STM32L431RCT6开发板研究串口通信(RS485)
热门文章
- python内置函数 — dir()
- 微软服务器出问题严重吗,微软承认更新又出问题了 Win10 新补丁修补性能问题失败...
- 菲涅尔区在线计算|无线传输损耗计算|dB(m,i)与功率(W)换算
- 视频剪辑软件:Premiere Pro 2023 中文直装版(带语音转字幕)
- 浅谈做芯片和建高楼的相似性和相通性
- 【数学知识】高一的集合知识的Python编程实现
- 利用宝塔搭建h5ai文件服务器做个人网盘
- 怎么删除打印机正在打印的文档?
- iApp输入法模式选择
- 微软Office办公软件哪个版本更好用?office365,office2022,2023等