赞
踩
来看点干货吧
我们来看看老师提供给我们的例子吧
#include <stdlib.h>//里面有atexit函数
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
void fork0()
{
if (fork() == 0) {
printf("Hello from child\n");
}
else {
printf("Hello from parent\n");
}
}
首先我们把它的进程图画出来
它在Linux环境下的运行结果为
void fork1()
{
int x = 1;
pid_t pid = fork();
if (pid == 0) {
printf("Child has x = %d\n", ++x);
}
else {
printf("Parent has x = %d\n", --x);
}
printf("Bye from process %d with x = %d\n", getpid(), x);
}
我们看一下它的进程图
在Linux环境下的运行结果为
void fork2()
{
printf("L0\n");
fork();
printf("L1\n");
fork();
printf("Bye\n");
}
它的进程图为
我们在看一下它在Linux环境下的运行结果
与之前的情况一样先执行完父进程,再执行子进程,一共是输出7个。
void fork3()
{
printf("L0\n");
fork();
printf("L1\n");
fork();
printf("L2\n");
fork();
printf("Bye\n");
}
这个例子其实与第三个例子差不多,只是多了一个fork
来看看它的进程图
它在Linux环境下的运行结果为
void fork4()
{
printf("L0\n");
if (fork() != 0) {
printf("L1\n");
if (fork() != 0) {
printf("L2\n");
}
}
printf("Bye\n");
}
它的进程图
在Linux环境下的运行结果为
void fork5()
{
printf("L0\n");
if (fork() == 0) {
printf("L1\n");
if (fork() == 0) {
printf("L2\n");
}
}
printf("Bye\n");
}
该例子与第五个例子类似
我们看看它在Linux环境下的运行结果
void cleanup(void) {
printf("Cleaning up\n");
}
void fork6()
{
atexit(cleanup);
fork();
exit(0);
}
它的运行结果为
void fork7()
{
if (fork() == 0) {
/* Child */
printf("Terminating Child, PID = %d\n", getpid());
exit(0);
}
else {
printf("Running Parent, PID = %d\n", getpid());
while (1)
; /* Infinite loop */
}
}
我们来看看它的进程图
#include <sys/types.h>
与#include <signal.h>
中int kill(pid_t pid,int sig);
详细的有关僵尸进程defunct的知识可见https://blog.csdn.net/wangjingyu00711/article/details/41958205
void fork8()
{
if (fork() == 0) {
/* Child */
printf("Running Child, PID = %d\n",
getpid());
while (1)
; /* Infinite loop */
}
else {
printf("Terminating Parent, PID = %d\n",
getpid());
exit(0);
}
}
我们来看看它的进程图吧
那它在Linux环境中的执行结果为什么呢?
在这个程序中,父进程是先执行完的,根据上面的知识是不会产生僵尸进程的,但是我在csdn上看了其他同学的博客,有一个同学的运行结果这个程序是也会产生僵尸进程的,而且他还使用了kill来杀死程序。我也不知道我的对不对,但是在我的系统中它是没有僵尸进程的。
void fork9() { int child_status; if (fork() == 0) { //child printf("HC: hello from child\n"); exit(0); } else { printf("HP: hello from parent\n"); wait(&child_status); printf("CT: child has terminated\n"); //parent } printf("Bye\n"); }
我还不太知道wait函数是一个怎样的函数,所以我们先来看看程序在linux环境下的运行结果吧
从运行结果可以知道父进程在执行完第一条printf后遇到wait函数,转接着去执行子进程,子进程执行完后又去执行父进程。
我们来看看wait到底是个什么函数吧
pid = wait(NULL)
我们知道了这些后来看看它的进程图吧
#define N 5 void fork10() { pid_t pid[N]; int i, child_status; for (i = 0; i < N; i++) if ((pid[i] = fork()) == 0) { exit(100+i); /* Child */ } for (i = 0; i < N; i++) { /* Parent */ pid_t wpid = wait(&child_status); if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n",wpid, WEXITSTATUS(child_status)); else{ printf("Child %d terminate abnormally\n", wpid);} } }
WIFEXITED(child_status)
是返回一个正常终止的子进程的退出状态。只有在WIFEXITED()为真时,才会定义这个状态。#define N 5 void fork11() { pid_t pid[N]; int i; int child_status; for (i = 0; i < N; i++) if ((pid[i] = fork()) == 0) exit(100+i); /* Child */ for (i = N-1; i >= 0; i--) { pid_t wpid = waitpid(pid[i], &child_status, 0); if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status)); else printf("Child %d terminate abnormally\n", wpid); } }
其实它与第十一个例子类似
它的运行结果为
#define N 5 void fork12() { pid_t pid[N]; int i; int child_status; for (i = 0; i < N; i++) if ((pid[i] = fork()) == 0) { /* Child: Infinite Loop */ while(1) ; } for (i = 0; i < N; i++) { printf("Killing process %d\n", pid[i]); kill(pid[i], SIGINT); } for (i = 0; i < N; i++) { pid_t wpid = wait(&child_status); if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status)); else printf("Child %d terminated abnormally\n", wpid); } }
父进程在进行五次fork后子进程一直处于循环中,之后父进程杀死子进程,父进程等待子进程正常结束,结束进程。
/* * int_handler - SIGINT handler */ void int_handler(int sig) { printf("Process %d received signal %d\n", getpid(), sig); /* Unsafe */ exit(0); } /* * fork13 - Simple signal handler example */ void fork13() { pid_t pid[N]; int i; int child_status; signal(SIGINT, int_handler); for (i = 0; i < N; i++) if ((pid[i] = fork()) == 0) { /* Child: Infinite Loop */ while(1) ; } for (i = 0; i < N; i++) { printf("Killing process %d\n", pid[i]); kill(pid[i], SIGINT); } for (i = 0; i < N; i++) { pid_t wpid = wait(&child_status); if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status)); else printf("Child %d terminated abnormally\n", wpid); } }
它的运行结果为
呃呃呃呃呃呃又来了一个signal函数,那我们又来了解一下吧
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);
void fork14() { pid_t pid[N]; int i; ccount = N; signal(SIGCHLD, child_handler); for (i = 0; i < N; i++) { if ((pid[i] = fork()) == 0) { sleep(1); exit(0); /* Child: Exit */ } } while (ccount > 0) ; } /* * child_handler2 - SIGCHLD handler that reaps all terminated children */ void child_handler2(int sig) { int child_status; pid_t pid; while ((pid = wait(&child_status)) > 0) { ccount--; printf("Received signal %d from process %d\n", sig, pid); /* Unsafe */ fflush(stdout); /* Unsafe */ } }
这个是它在Linux环境下的运行结果
但是我有点看不太懂这个程序,它应该也是一个僵尸进程,因为shell命令行没有显示。
按下Ctrl+Z时它会挂起
ps命令后可以看到它是有四个僵尸进程,我输入kill -9也不会杀死进程,唉,我太蠢了
void child_handler(int sig) { int child_status; pid_t pid = wait(&child_status); ccount--; printf("Received SIGCHLD signal %d for process %d\n", sig, pid); /* Unsafe */ fflush(stdout); /* Unsafe */ } void fork15() { pid_t pid[N]; int i; ccount = N; signal(SIGCHLD, child_handler2); for (i = 0; i < N; i++) if ((pid[i] = fork()) == 0) { sleep(1); exit(0); /* Child: Exit */ } while (ccount > 0) { pause(); } }
运行结果为
void fork16()
{
if (fork() == 0) {
printf("Child1: pid=%d pgrp=%d\n",
getpid(), getpgrp());
if (fork() == 0)
printf("Child2: pid=%d pgrp=%d\n",
getpid(), getpgrp());
while(1);
}
}
getpgrp()是用来取得目前进程所属的组识别码,相当于调用getpid()
可以看到子进程的组识别码是一样的
ps后的结果为
void fork17()
{
if (fork() == 0) {
printf("Child: pid=%d pgrp=%d\n",
getpid(), getpgrp());
}
else {
printf("Parent: pid=%d pgrp=%d\n",
getpid(), getpgrp());
}
while(1);
}
对于进程组ID,所有的子进程识别码ID与父进程识别码ID相同。对于进程组ID一般来说,一个进程在shell下执行,shell程序就将该进程的进程组PID赋给该进程的进程组的ID,从该进程派生的子进程都拥有福进程所属的进程组ID,除非父进程将子进程的所属组ID设置成与该子进程的PID一样。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。