Linux进程实践(2) --僵尸进程与文件共享
孤儿进程与僵尸进程
孤儿进程:
如果父进程先退出,子进程还没退出那么子进程的父进程将变为init进程。(注:任何一个进程都必须有父进程)
//生成孤儿进程 int main(int argc, char *argv[]) { pid_t pid = fork(); if (pid < 0) err_exit("fork error"); else if (pid > 0) exit(0); else { sleep(10); cout << "Child, ppid = " << getppid() << endl; } exit(0); }
僵尸进程:
如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就成为僵尸进程。
//生成僵尸进程 int main(int argc, char *argv[]) { pid_t pid = fork(); if (pid < 0) err_exit("fork error"); else if (pid == 0) exit(0); else { sleep(50); } exit(0); }
附-查询父子进程状态
ps -le | grep main
避免僵尸进程
signal(SIGCHLD, SIG_IGN);
//示例: 避免僵尸进程 int main(int argc, char *argv[]) { signal(SIGCHLD, SIG_IGN); pid_t pid = fork(); if (pid < 0) err_exit("fork error"); else if (pid == 0) exit(0); else { sleep(50); } exit(0); }
文件共享
父进程的所有文件描述符都被复制到子进程中, 就好像调用了dup函数, 父进程和子进程每个相同的打开文件描述符共享一个文件表项(因此, 父子进程共享同一个文件偏移量);
//根据上图: 理解下面这段程序和下图的演示 int main(int argc, char *argv[]) { signal(SIGCHLD, SIG_IGN); int fd = open("test.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd == -1) err_exit("file open error"); cout << "We Don`t flash memory\n"; char buf[BUFSIZ]; bzero(buf, sizeof(buf)); pid_t pid = fork(); if (pid < 0) err_exit("fork error"); else if (pid > 0) { strcpy(buf, "Parent..."); write(fd, buf, strlen(buf)); close(fd); cout << "fd = " << fd << endl; exit(0); } else if (pid == 0) { strcpy(buf, "Child..."); write(fd, buf, strlen(buf)); close(fd); cout << "fd = " << fd << endl; exit(0); } }
fork VS vfork
在UNIX/Linux中的fork还没实现copy on write(写时复制)技术之前。Unix设计者很关心fork之后立刻执行exec所造成的地址空间浪费,所以引入了vfork系统调用。其中,vfork子进程与父进程共享数据段,并不真正复制父进程内存,因此在vfork之后执行exec系列函数,并不会导致地址空间浪费以及无用的空间复制时间.而且,即使fork实现了copy on write,效率也没有vfork高.
但是,vfork有个限制,子进程必须立刻执行_exit或者exec系列函数。因此我们不推荐使用vfork,因为几乎每一个vfork的实现,都或多或少存在一定的问题(可以尝试在vfork之后的子进程中既不执行_exit,也不执行exec函数)。
fork与vfork的区别
1. fork子进程拷贝父进程的数据段(但是现在提供了写时复制技术,只有当子进程真正需要写内存时,才复制出该内存的一段副本),因此,在父进程/子进程中对全局变量所做的修改并不会影响子进程/父进程的数据内容.
vfork子进程与父进程共享数据段,因此父子进程对数据的更新是同步的;
2. fork父、子进程的执行次序是未知的,取决于操作系统的调度算法
vfork:子进程先运行,父进程后运行;
//示例1:vfork出错情况 //在Linux 2.6内核上会持续执行,不会退出 //而在Linux 3.13内核上, 则会引发core dump int main() { int iNumber = 0; pid_t pid = vfork(); if (pid == -1) { perror("fork"); return -1; } else if (pid > 0) { cout << "In Parent Program..." << endl; cout << "iNumber = " << iNumber << endl; cout << "pid = " << static_cast<int>(getpid()); cout << "\t ppid = " << static_cast<int>(getppid()) << endl; //_exit(0); } else if (pid == 0) { iNumber ++; cout << "In Child Program..." << endl; cout << "iNumber = " << iNumber << endl; cout << "pid = " << static_cast<int>(getpid()); cout << "\t ppid = " << static_cast<int>(getppid()) << endl; //_exit(0); } return 0; }
//示例2: 父进程/子进程修改全局数据的情况 int main() { int iNumber = 10; cout << "Before vfork, pid = " << getpid() << endl; //对比fork() pid_t pid = vfork(); if (pid == -1) err_exit("fork"); else if (pid > 0) { sleep(4); cout << "Parent, iNumber: " << iNumber << endl; } else if (pid == 0) { ++ iNumber; cout << "Child, iNumber = " << iNumber << endl; _exit(0); } return 0; }
//示例3:用vfork执行当前目录下的hello程序 int main() { int iNumber = 0; pid_t pid = vfork(); if (pid == -1) { perror("fork"); return -1; } else if (pid > 0) { cout << "In Parent Program..." << endl; cout << "iNumber = " << iNumber << endl; cout << "pid = " << static_cast<int>(getpid()); cout << "\t ppid = " << static_cast<int>(getppid()) << endl; } else if (pid == 0) { iNumber ++; cout << "In Child Program..." << endl; cout << "iNumber = " << iNumber << endl; cout << "pid = " << static_cast<int>(getpid()); cout << "\t ppid = " << static_cast<int>(getppid()) << endl; //将自己写的程序启动起来 execve("./hello",NULL,NULL); _exit(0); } return 0; }
//测试4,用vfork执行系统命令 int main() { int iNumber = 0; pid_t pid = vfork(); if (pid == -1) { perror("fork"); return -1; } else if (pid > 0) { cout << "In Parent Program..." << endl; cout << "iNumber = " << iNumber << endl; cout << "pid = " << static_cast<int>(getpid()); cout << "\t ppid = " << static_cast<int>(getppid()) << endl; } else if (pid == 0) { iNumber ++; cout << "In Child Program..." << endl; cout << "iNumber = " << iNumber << endl; cout << "pid = " << static_cast<int>(getpid()); cout << "\t ppid = " << static_cast<int>(getppid()) << endl; //将ls命令启动起来,注意:由于C++严格的类型转换机制,需要在字符串前加(char*) char *const args[] = {(char *)"/bin/ls", (char *)"-l", NULL}; int res = execve("/bin/ls",args,NULL); if (res == -1) { perror("execve"); _exit(1); } _exit(0); } return 0; }
Linux进程实践(2) --僵尸进程与文件共享的更多相关文章
- 脚本_查找 Linux 系统中的僵尸进程
#!bin/bash#功能:查找Linux系统中的僵尸进程#作者:liusingbon#使用awk判断ps命令输出的第8列为Z时,显示该进程的 PID 和进程命令ps aux |awk '{if($8 ...
- Linux查找并杀死僵尸进程
1.查看系统是否有僵尸进程 使用Top命令查找,当zombie前的数量不为0时,即系统内存在相应数量的僵尸进程. 2.定位僵尸进程 使用命令ps -A -ostat,ppid,pid,cmd |gre ...
- Linux查找并杀死僵尸进程(转)
1.查看系统是否有僵尸进程 使用Top命令查找,当zombie前的数量不为0时,即系统内存在相应数量的僵尸进程. 2.定位僵尸进程 使用命令ps -A -ostat,ppid,pid,cmd |gre ...
- paip.杀不死进程的原因--僵尸进程的解决.txt
paip.杀不死进程的原因--僵尸进程的解决.txt 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn ...
- [并发编程 - socketserver模块实现并发、[进程查看父子进程pid、僵尸进程、孤儿进程、守护进程、互斥锁、队列、生产者消费者模型]
[并发编程 - socketserver模块实现并发.[进程查看父子进程pid.僵尸进程.孤儿进程.守护进程.互斥锁.队列.生产者消费者模型] socketserver模块实现并发 基于tcp的套接字 ...
- Linux进程实践(5) --守护进程
概述 守护进程是在需要在后台长期运行不受终端控制的进程,通常情况下守护进程在系统启动时自动运行,在服务器关闭的时候自动关闭:守护进程的名称通常以d结尾,比如sshd.xinetd.crond.atd等 ...
- Linux -- 进程管理之僵尸进程
UNIX 存在一种机制:在每个进程退出的同时,操作系统释放该进程所有资源,但仍然保留一定的信息(PID / Status / runtime),直到父进程执行 wait() / waitpid(),以 ...
- 041_查找 Linux 系统中的僵尸进程
#!/bin/bash#awk 判断 ps 命令输出的第 8 列为 Z 是僵尸进程,显示该进程的 PID 和进程命令 ps aux |awk '{if($8 == "Z"){pri ...
- C语言在Linux下创建一个僵尸进程
第三章编程题3.12 1.僵尸进程是什么 每一个进程都有一个PCB(进程控制块),其中包含进程执行的状态等一系列信息. 当父进程fork()出一个子进程,子进程执行结束后操作系统会回收子进程使用的内存 ...
随机推荐
- 论文答辩ppt要怎么写
1.总体原则: 字大.字少.图多.要有重点 字体建议:正文要用黑体(如微软雅黑),标题可使用宋体或者黑体(如微软雅黑) 2. 主要分为两大部分: 2.1系统介绍 系统概述:概述自己系统主要是做了些什么 ...
- [CSDN_Markdown]使用LaTeX基本数学公式
简介 以前我很头疼在博文里写公式,一直期盼CSDN的博文编辑器能支持LaTeX 公式输入,今天终于可以使用这个功能了!此文主要讨论如何在CSDN的Markdown编辑器中写 LaTeX 公式! 使用L ...
- [CSDN_Markdown] 使用CSDN Markdown编辑器
简介 最近CSDN支持Markdown语法写博客了,甚是欢喜.前几天写了一篇实验了下,感觉不错.准备写几篇文章介绍一下如何使用CSDN的Markdown编辑器写博客,不求全面,但求够用,望大家批评指正 ...
- named let 递归和闭包的利器
named let和递归,闭包联系十分密切.而且还是提高性能的重要手段.先来看一个make-list函数的模拟,最原始的写法大概是: (define (imake-list n member) ( n ...
- Android仿淘宝购物车demo
夏的热情渐渐退去,秋如期而至,丰收的季节,小编继续着实习之路,走着走着,就走到了购物车,逛过淘宝或者是京东的小伙伴都知道购物车里面的宝贝可不止一件,对于爱购物的姑娘来说,购物车里面的商品恐怕是爆满,添 ...
- 【一天一道Leetcode】#203.Remove Linked List Elements
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 我的个人博客已创建,欢迎大家持续关注! 一天一道le ...
- UNIX网络编程——TCP—经受时延与nagle算法、滑动窗口、拥塞窗口
1.经受时延: TCP在接收到数据时并不立即发送ACK,相反,它推迟发送,以便将ACK与需要沿该方向发送的数据一起发送,时延为200ms,超过时延范围,发送确认. 2.nagle算法: 一个TCP连接 ...
- (NO.00004)iOS实现打砖块游戏(十四):3球道具的实现
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 反弹棒变化道具实现前面已经介绍过了,我们下面可以在小球上做些文章 ...
- 套接字输入流——InputStream
输入缓冲装置里面必须要包含读取字符的通道,否则就谈不上缓冲了,这个通道就是InputStream,它属于jdk中java.io包的类,有了它我们就可以从源头读取字符,它的来源可以有多种多样,这里主要探 ...
- 03安卓TextView
一 TextView 父类 : View >概念:文本控件 :文本内容的显示 默认配置不可编辑 子类EditText可以编辑 *********************** ...