linux C 多进程编程

linux 多进程编程有如下要点

第一:首当其冲的是进程状态,我把本地的ubuntu进程截图了一份,请看:

进程的状态如下:

R:running,运行状态。

S:可中断的睡眠状态。

D:不可中断的睡眠状态。

T:暂停状态。

Z:僵尸状态。

<:高优先级别

N:低优先级别

+:前台进程

 

第二,创建进程

函数定义:pid_t fork(); 

成功时,返回进程id,失败时返回-1. 参考例子如下:

#include <stdio.h>
#include <unistd.h>
int main()
{
   pid_t pid=fork();
   if(pid==0)
   {
      fputs("Hi i am child proc...",stdout);
   }
   else{
      fputs("Child proc id is: %d \n ",stdout);
      sleep(30);
   }
   if(pid==0)
   {
      puts("End child process");
   }
   else{
      puts("End parent process");
   }
   return 0;
}

  当pid==0时,是子进程代码运行区域。其他则是父进程运行区域。由于父进程没有接收到子进程的返回值,这样子进程会转换为僵尸进程。

第三 僵尸进程的处理

1)wait 方法:wait方法会一直阻塞当前进程运行,直到有当前进程的子进程结束,wait方法会返回。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>


int main()
{
    int status;
    pid_t id=fork();
    if(id==0)
    {
      return 4;
    }
    else{
      printf("child proc id is: %d \n",id);
      wait(&status);
      if(WIFEXITED(status))
      {
          printf("THe child process return normal:%d \n ",WEXITSTATUS(status));
      }
      sleep(30);
    }
    if(id==0)
    {
         fputs("The child process ends..\n",stdout);
    }
    else{
         fputs("The parent process ends..\n",stdout);
    } 
    return 0;
}

 2)waitpid 方法:该方法不会阻塞当前进程。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>


int main()
{
    pid_t pid = fork();
    int status;
    if(pid==0) 
    {
       puts("The child process running....");
       sleep(9);
       exit(24);
    }
    else{
       while(!waitpid(pid,&status,WNOHANG))   
       {
            sleep(3);
            puts("3 seconds...");
       }
       if(WIFEXITED(status))
       {
            printf("Child sent is: %d \n",WEXITSTATUS(status));
       }
    }
    return 0;
}

  

3)使用信号处理机制,核心在于signal 方法

signal 方法第一个参数为事件名称。第二个参数为第一个参数事件发生时,需要调用的函数。

事件主要有三个:

SIGCHLD,当前进程的子进程结束时会自动发出这个信号。

SIGINT,当用户按ctrl c时,系统会发出这个信号。

SIGALRM.系统的alarm函数运行到期后,会发出这个信号。

例子如下:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void timeout(int sig)
{
    printf("time out is: %d \n",sig);
    if(sig==SIGALRM)
    {
        puts("time out....");
    }
    alarm(2);
}

void keycontrol(int sig)
{
    printf("keycontrol is: %d \n",sig);
    if(sig==SIGINT)
    {
       puts("Ctrl c pressed..");
    } 
} 

int main()
{
    signal(SIGINT,keycontrol); 
    signal(SIGALRM,timeout);
    alarm(3);
    puts("hahahahahah");
    int i;
    for(i=0;i<3;i++)
    {
       puts("wait.....");
       sleep(30);
    }
    return 0;
}

  

4)sigaction函数,这个函数是跨平台的。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void timeout(int sig)
{
    if(sig==SIGALRM)
    {
       puts("time out....");
    }
    alarm(2); 
}
int main()
{
   int i=0;
   struct sigaction sig;
   sig.sa_handler=timeout;
   sig.sa_flags=0;
   sigemptyset(&sig.sa_mask);
   sigaction(SIGALRM,&sig,0);
   alarm(2);
   for(i=0;i<100;i++)   
   {
        sleep(100); 
        puts("wait....");
   }
   return 0;
}

  这里结构体sigaction的sa_flags=0,sa_mask 都用0即可。sa_handler用来指定处理函数。

 

第四:进程通信

由于进程是独立的内存结构,因此进程间不存在共享变量,所以使用管道,管道是内核所有的。见如下例子:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>

void readProc(int sig)
{
    if(sig==SIGCHLD)
    {
        int status;
        waitpid(-1,&status,WNOHANG);
        if(WIFEXITED(status))
        {
            printf("received from child is: %d \n",WEXITSTATUS(status));
            sleep(30);
        }
    }
}

int main()
{
   struct sigaction sig;
   sig.sa_handler=readProc;
   sigemptyset(&sig.sa_mask);
   sig.sa_flags=0;
   sigaction(SIGCHLD,&sig,0);
   int fd1[2],fd2[2];
   char str1[] = "who are you";
   char str2[] = "I am lucy";
   char buf[50];
   pipe(fd1);
   pipe(fd2);
   pid_t id;
   id = fork(); 
   if(id==0)
   {
      write(fd1[1],str1,sizeof(str1));
      read(fd2[0],buf,50);
      printf("child proc recived from parent is: %s \n",buf);
      return 88;
   }else{
      read(fd1[0],buf,50);
      write(fd2[1],str2,sizeof(str2));
      printf("parent proc recived from child is: %s \n",buf);
      sleep(40);
   }
   return 0;
}

  

 

posted on 2017-07-27 11:17  ^~~^  阅读(...)  评论(... 编辑 收藏

导航