TCP/IP网络编程——多进程与僵尸进程

进程:占用内存空间的正在运行的程序。

下面通过这一段程序理解多进程:

fork.c

//父进程:fork返回子进程ID,子进程:返回0
//最终运行结果:父进程:gval=11,lval=26;
//子进程:gval=12,lval=25;
#include <stdio.h>
#include <unistd.h>
#include <boost/graph/graph_concepts.hpp>

int gval=10;

int main(void)
{
  int lval=20;
  lval+=5;
  gval++;
  pid_t pid=fork();	//发生复制点
  if(pid==0)
    gval++;
  else
    lval++;
  
  return 0;
}

僵尸进程:exit和return返回的值会给操作系统,而操作系统不会销毁子进程,直到把这些值传给该子进程的父进程。

zombie.c

//在父进程休眠的30s时间里,子进程会变成僵尸进程
//操作系统不会销毁子进程,直到父进程获得子进程的结束状态值
#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
  pid_t pid=fork();
  
  if(pid==0)
    puts("child process");
  else
  {
    printf("child process ID:%d \n", pid);
    sleep(30);	//父进程休眠30s
  }
  
  if(pid==0)
    puts("End child process");
  else
    puts("End parent process");
  
  return 0;
}

销毁僵尸进程方法1:利用wait函数(父进程主动请求获取子进程的返回值)

//利用wait函数终止子进程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void)
{
  int status;
  pid_t pid=fork();	//创建子进程1
  
  if(pid==0)
    return 3;
  else
  {
    printf("child pid:%d \n", pid);
    pid=fork();	//创建子进程2
    if(pid==0)
      exit(7);
    else
    {
      printf("child pid:%d \n", pid);
      //销毁第一个子进程
      wait(&status);
      if(WIFEXITED(status))
	printf("child send1: %d \n", WEXITSTATUS(status));
      //销毁第二个子进程
      wait(&status);
      if(WIFEXITED(status))
	printf("child send1: %d \n", WEXITSTATUS(status));
      
      sleep(30);	//父进程休眠30s
    }
  }
  
  return 0;
}

方法2:利用waitpid函数(wait会引起阻塞,而waitpid不会)

//使用wait函数会阻塞程序直到有子进程终止
//waitpid可以避免这个问题
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void)
{
  int status;
  pid_t pid=fork();
  
  if(pid==0)
  {
    sleep(15);
    return 24;
  }
  else
  {
    //WNOHANG:没有终止的子进程不会阻塞程序,而会返回0并退出函数
    while(!waitpid(pid, &status, WNOHANG))
    {
      sleep(3);
      puts("sleep 3s");
    }
    
    if(WIFEXITED(status))
	printf("child send: %d \n", WEXITSTATUS(status));
  }
  
  return 0;
}

方法3:利用信号处理技术消灭僵尸进程

//利用信号处理技术消灭僵尸进程
//信号处理:在特定事件发生时由操作系统向进程发送信号,
//为了响应信号,进程执行与信号相关的自定义操作。
//使用sigaction函数
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>

//一旦有子进程结束就调用这个函数
void read_childproc(int sig)
{
  int status;
  pid_t id=waitpid(-1, &status, WNOHANG);
  if(WIFEXITED(status))
  {
    printf("remove proc id: %d \n", id);
    printf("child send: %d \n", WEXITSTATUS(status));
  }
}

int main(void)
{
  pid_t pid;
  struct sigaction act;
  act.sa_handler=read_childproc;
  sigemptyset(&act.sa_mask);
  act.sa_flags=0;
  sigaction(SIGCHLD, &act, 0);
  
  pid=fork();
  if(pid==0)	//子进程执行区域
  {
    puts("Im child process1");
    sleep(10);
    return 12;
  }
  else	//父进程执行区域
  {
    printf("child proc id: %d \n", pid);
    pid=fork();
    if(pid==0)
    {
      puts("Im child process2");
      sleep(10);
      exit(24);
    }
    else
    {
      int i;
      printf("child proc id: %d \n", pid);
      for(i=0;i<5;i++)
      {
	puts("wait...");
	sleep(5);
      }
    }
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/u012411498/article/details/80499240