//以下是下列代码的头文件
/*
* forks.c - Examples of Unix process control
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
(零)
/*
* fork0 - The simplest fork example
* Call once, return twice
* Creates child that is identical to parent
* Returns 0 to child process
* Returns child PID to parent process
*/
void fork0()
{
if (fork() == 0) {
printf("Hello from child\n");
}
else {
printf("Hello from parent\n");
}
}
使用fork创建一个子进程,子进程打印出(“Hello from child”);
父进程打印出(“Hello from parent”);
(一)
/*
* fork1 - Simple fork example
* Parent and child both run same code
* Child starts with identical private state
*/
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);
}
使用getpid可以得到创建子进程的ID号
父进程和子进程是独立运行的
(二)
/*
* fork2 - Two consecutive forks
* Both parent and child can continue forking
* Ordering undetermined
*/
void fork2()
{
printf("L0\n");
fork();
printf("L1\n");
fork();
printf("Bye\n");
}
(三)
/*
* fork3 - Three consective forks
* Parent and child can continue forking
*/
void fork3()
{
printf("L0\n");
fork();
printf("L1\n");
fork();
printf("L2\n");
fork();
printf("Bye\n");
}
(四)
/*
* fork4 - Nested forks in parents
*/
void fork4()
{
printf("L0\n");
if (fork() != 0) {
printf("L1\n");
if (fork() != 0) {
printf("L2\n");
}
}
printf("Bye\n");
}
(五)
/*
* fork5 - Nested forks in children
*/
void fork5()
{
printf("L0\n");
if(fork()==0){
printf("L1\n");
if(fork()==0){
printf("L2\n");
}
}
printf("Bye\n");
}
``
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191129175336666.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191129180351581.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3oxOTExNzI1MTQ1,size_16,color_FFFFFF,t_70)
**(六)**
void cleanup(void) {
printf(“Cleaning up\n”);
}
/*
- fork6 - Exit system call terminates process
- call once, return never
*/
void fork6()
{
atexit(cleanup);
fork();
exit(0);
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191129180955952.png)
**(七)**
/*
- fork7 - Demonstration of zombies.
- Run in background and then perform ps
/
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 */
}
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191129181226323.png)
子进程正常退出,父进程进入死循环,所以要使用Ctrl+C终止进程
**(八)**
/*
- fork8 - Demonstration of nonterminating child.
- Child still running even though parent terminated
- Must kill explicitly
/
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);
}
}
``
子进程进入死循环,父进程正常退出,回收子进程。
(九)
/*
* fork9 - synchronizing with and reaping children (wait)
*/
void fork9()
{
int child_status;
if(fork()==0){
printf("HC:hello from child\n");
exit(0);
}else{
printf("HP:hello from parent\n");
wait(&child_status);
printf("CT:child has terminated\n");
}
printf("Bye\n");
}
wait表示等待子进程结束以后执行wait后续的代码,所以最后打印出CT:child has terminated
(十)
#define N 5
/*
* fork10 - Synchronizing with multiple children (wait)
* Reaps children in arbitrary order
* WIFEXITED and WEXITSTATUS to get info about terminated children
*/
void fork10()
{
pid_t pid[N];
int i,child_status;
for(i=0;i<N;i++)
if((pid[i]=fork())==0){
exit(100+i);
}
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 terminate abnormally\n",wpid);
}
}
创建了5个子进程,并且将退出状态码返回给父进程。
(十一)
/*
*fork11
*Reaps children in reverse order
*/
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);
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);
}
}
相比于fork10,这里将输出进行排序输出
(十二)
/*
* fork12 - Sending signals with the kill() function
*/
void fork12()
{
pid_t pid[N];
int i;
int child_status;
for(i=0;i<N;i++)
if((pid[i]=fork())==0){
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);
}
}
`
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191129231017804.png)
由于子进程进入了死循环,所以使用kill将子进程都杀死,因为子进程没有创建成功,所以执行了(Child %d terminated abnormally")
**(十三)**
/*
*int_handler -SIGINT handler
/
void int_handler(int sig)
{
printf(“Process %d received signal %d\n”,getpid(),sig);
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){
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);
}
}
``
fork13相比与fork12将处理函数转给自定义的函数进行处理。
(十四)
/*
* child_handler - SIGCHLD handler that reaps one terminated child
*/
int ccount = 0;
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);
fflush(stdout);
}
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);
}
}
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);
fflush(stdout);
}
}
/*
* fork15 - Using a handler that reaps multiple children
*/
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);
}
while(ccount>0){
pause();
}
}
这里使用pause将暂停,先让子进程的5个循环做完。
(十六)
/*
* fork16 - Demonstration of using /bin/kill program
*/
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);
}
}
(十七)
/*
* Demonstration of using ctrl-c and ctrl-z
*/
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);
}
进入死循环时,可以使用Ctrl+c进行终止,使用Ctrl+z进行挂起