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;
}

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM