僵尸进程,孤儿进程,wait,exit,execl等函数使用要点
来源:互联网 发布:招银网络 编辑:程序博客网 时间:2024/05/20 07:51
进程号为1的进程是所有进程的主先进程init
如何查看进程:ps uax
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int a = 8;
printf("current process id:%d\n",getpid());
pid = fork();
if( pid > 0 )//父进程所做之事
{
printf("a = %d\n",a);
printf(" pid = %d\n",pid);//子进程
printf(" ppid = %d\n",getpid());//父进程
//while(1);
}else if( pid == 0 )//子进程所做之万
{
a++;
printf("aa = %d\n",a);
printf("child pid = %d\n",getpid());//子进程
printf("parent pid = %d\n",getppid());//父进程
//while(1);
}else{
printf("fork error!\n");
}
exit(0);
}
/*
* fork函数:
* 1.fork函数用于创建子进程。子进程
* 继承父进程之前运行的一切状态,并
* 且拷贝父进程的地址空间,成为父
* 进程的一个副本。子进程从fork函数
* 的下一句话开始运行。
* 2.fork函数不能保证父进程和子进程
* 哪个先运行。
* 这里相当于两个进程在执行,所以出现的结果是六个
*/
结果:
current process id:1995
a = 8
pid = 1996
ppid = 1995
aa = 9
child pid = 1996
parent pid = 1995
僵尸进程的产生:
/*
============================================================================
Name : jianshiprocess.c
Author :
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
//长生僵尸进程
#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include<sys/types.h>
//僵尸进程:
//子进程在父进程前退出,此时子进程成为僵尸进程。
//孤儿进程:
//父进程在子进程之前退出,此时子进程成为孤儿进程,此子进程由init进程零养,(也就是说init进程成为子进程的父进程,init进程是所有孤儿进程的父进程)
//着两种都是要避免的
int main(void)
{
pid_t pid;
pid=fork();
if(pid>0)
{
sleep(10);//让父进程等在这里,之后被唤醒
}
else if(pid==0)
{
printf("child%d",getpid());
printf("p%d",getppid());
exit(0);//成为僵尸进程后,占用进程好
}
else
{
puts("wrong");
exit(0);
}
return EXIT_SUCCESS;
}
孤儿进程:
/*
============================================================================
Name : guerprocess.c
Author :
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main(void) {
int i;
pid_t pid;
printf("current process id:%d\n",getpid());
pid=fork();
if(pid>0)
{
exit(0);//成为僵尸进程后,占用进程好
}
else if(pid==0)
{
for(i=0;i<20;i++)
{
printf("child:%d\n",getpid());
printf("parent:%d\n",getppid());
}
}
else
{
puts("wrong");
exit(0);
}
return EXIT_SUCCESS;
}
奇怪的现象:如果在这个进程的执行过程中,按ctrl+c阻止程序的进行,会发现阻止不了,因为此时的子进程成了孤儿进程,成了主进程的守护进程,因为它的父进程是init进程,而ctrl+c只能阻止前台运行的程序
2:
return 与exit的区别:
return 用于函数返回,只有main函数调用时,进程才退出
而exit函数被调用,此进程直接退出
exit与_exit的相同点:
都是用于进程退出。
不同点:
exit函数在进程退出之前,会刷新文件缓冲区到文件中。
_exit在进程退出之前,不会刷新缓冲区,也就说直接丢弃缓冲区里面的内容
fork与vfork
执行fork创建子进程时,子进程将拷贝父进程的数据段、堆段和栈段,此时父子进程的数据一致当互相独立,各不影响,子进程对数据的处理不影响父进程。(其实当父子进程都不对三个段进行写操作时,父子进程仍然共享数据段、堆段和栈段,当有任何一方有写操作时,才产生副本,这种方式成为写是复制)
vfork与fork区别有两点:1、vfork创建的子进程与父进程共享数据段,2、vfork创建的子进程优先于父进程执行,当子进程执行时,父进程进入阻塞状态。
所以vfork产生的子进程对数据的修改一定可以影响到父进程的数据
exit与_exit
exit:当执行exit时,终止处理程序,执行标准的I/O清楚操作(将缓存中文件写入),调用atexit,调用_exit。由此可见,exit是加强版的_exit.
_exit:通知内核,进程结束
代码区别:printf("hello");
exit(0);//
结果:输出hello,刷新缓冲区
printf("hello");
_exit(0)
结果,不输出,直接丢弃缓冲区里面的内容
3.wait函数:
wait(等待子进程中断或结束)#include<sys/wait.h>
1.调用到wait函数的进程直接阻塞
2.一般由父进程调用,用于回收子进程退出时,其所占有的资源,避免其成为僵尸进程
3.如果一个进程调用到此函数,且其没有子进程,wait函数直接返回
4.处理SIGCHL信号(当子进程状态改变时,内核会向其父进程发送SIGCHL信号,用户进程对于此信号的默认处理方式为忽略)
5.调用到wait函数进程的任何一个子进程退出,此函数返回。(或者搜到SIGCHL函数则也退出)
6.获取子进程的状态值wait(&status)
如:exit(7),7是整形常量,占32位,取整形常量的低八位,放在status的32位的高八位,如果把status里面的值右移八位,就又变成7(status是个整形变量),因为它的低八位要被其它信号量占用.(exit里面的值只能是0-255)
一个wait只能回收一个子进程的空间
7.无法确定回收某个指定的子进程
j进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL,就象下面这样
- pid = wait(NULL);
如果成功,wait会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD。
如果参数status的值不是NULL,wait就会把子进程退出时的状态取出并存入其中,这是一个整数值(int),指出了子进程是正常退出还是被非正常结束的(一个进程也可以被其他进程用信号结束,我们将在以后的文章中介绍),以及正常结束时的返回值,或被哪一个信号结束的等信息。由于这些信息被存放在一个整数的不同二进制位中,所以用常规的方法读取会非常麻烦,人们就设计了一套专门的宏(macro)来完成这项工作,下面我们来学习一下其中最常用的两个:
1,WIFEXITED(status)这个宏用来指出子进程是否为正常退出的,如果是,它会返回一个非零值。
(请注意,虽然名字一样,这里的参数status并不同于wait唯一的参数--指向整数的指针status,而是那个指针所指向的整数,切记不要搞混了。)
2, WEXITSTATUS(status)当WIFEXITED返回非零值时,我们可以用这个宏来提取子进程的返回值,如果子进程调用exit(5)退出,WEXITSTATUS(status)就会返回5;如果子进程调用exit(7),WEXITSTATUS(status)就会返回7。请注意,如果进程不是正常退出的,也就是说,WIFEXITED返回0,这个值就毫无意义。
/*============================================================================
Name : wait.c
Author :
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
//多用于父进程和多进程中
#include <stdio.h>
#include <stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
int main(void) {
pid_t pid;
int status;
pid=fork();
if(pid>0)
{
wait(&status);
printf("this is a parent process\n");
if(WIFEXITED(status))
{
printf("status is %d \n",WEXITSTATUS(status));
}
exit(0);
}
else if(pid==0)
{
printf("this is a child process!\n");
exit(7);
}
else
{
printf("fork error!\n");
exit(1);
}
return EXIT_SUCCESS;
}
4.wait_pid
waitpid(等待子进程中断或结束)
#include<sys/wait.h>
pid<-1 等待进程组识别码为pid绝对值的任何子进程。
pid=-1 等待任何子进程,相当于wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为pid的子进程。
参数option可以为0 或下面的OR 组合
WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。
WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
子进程的结束状态返回后存于status,底下有几个宏可判别结束情况
WIFEXITED(status)如果子进程正常结束则为非0值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真
WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status)取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。 wait_pid(pid,&status,0);//等待指定的子进程,回收指定的子进程
execl:
execl(执行文件)
main()
{
execl(“/bin/ls”,”ls”,”-al”,”/etc/passwd”,(char * )0);
}
-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd执行之后的语句很有可能被擦除掉,而之前的还在
- 僵尸进程,孤儿进程,wait,exit,execl等函数使用要点
- 进程编程中的孤儿和僵尸进程--wait/waitpid函数
- 孤儿进程、僵尸进程
- 僵尸进程 孤儿进程
- 僵尸进程&孤儿进程
- 僵尸进程,孤儿进程
- 僵尸进程 孤儿进程
- 僵尸进程&孤儿进程
- 孤儿进程&僵尸进程
- 僵尸进程&孤儿进程
- 孤儿进程/僵尸进程
- 孤儿和僵尸进程
- 僵尸、孤儿、守护进程
- 孤儿进程和僵尸进程
- 僵尸进程和孤儿进程
- 孤儿进程和僵尸进程
- 孤儿进程和僵尸进程
- 僵尸进程与孤儿进程
- ANDROID 开发:谷歌地图开发入门(1)--- google map api V1,V2,V3。
- iOS错误之expected specifier-qualifier-list解决方案
- TestNG官方文档中文版(05)—— 测试方法、测试类和测试组
- 小知识点日志2012-11-22 至 2013-1-9
- 几种函数调用方式
- 僵尸进程,孤儿进程,wait,exit,execl等函数使用要点
- 日志分析器
- ZOJ1610 Count the Colors
- ASP.NET MVC3 系列教程 - Razor视图引擎基础语法
- TestNG官方文档中文版(06)—— 测试结果
- 使用mdev在/dev/下创建子目录放置设备节点
- C语言产生的泊松过程流
- 给ExtJS的Grid增加两行tbar
- 导航栏目与内容对应的java解决