Linux下進程間通訊(嵌入式面試題)

                                                                          2016-10-28,14:53,Fri編程

   題目:c編程---在終端輸入(Num,Cmd),Num表明隊員號,Cmd表明命令。Cmd爲1,奔跑; Cmd爲2,顯示已奔跑時間(精確到ms); Cmd爲3,中止奔跑並顯示全部隊員的狀態(狀態0:未奔跑; 狀態1:正在奔跑; 狀態2:奔跑過但已中止)。併發

  單進程:每一個隊員匹配一個信息結構體:Struct{int num;int cmd;int time;int status};使用switch(msg[num].cmd) 執行對應操做來改變 msg[num].timemsg[num.]status便可。   ide

  多進程:每一個隊員匹配一個進程。子進程睡眠態-->狀態1,運行態-->狀態2,暫停態-->狀態3. 而進程間通訊咱們選用消息隊列和信號的方法:函數

子進程被建立以後,因msgrcv()而處於阻塞態(即睡眠態)。接收到特定msg,便進入運行態while(1)。接收SIGUSR1信號時,將運行時間發送給父進程。接收到SIGSTOP信號時進入暫停態,且父進程中獲取各子程序的狀態。spa


simple flowchartresult

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 1 #include "head.h"
 2 
 3 struct {
 4     long mtype;
 5     int  mcmd;
 6     clock_t  mtv;
 7 }msg;
 8 pid_t  pid[6];
 9 int fd[6];
10 key_t key;
11 char dir[64];
12 char * p;
13 int msqid, i, num, cmd, status;
14 
15 void send_running_time(int arg);  //得到運行時間併發送
16 void recv_running_time();
17 void recycle_child(int arg);   //殺死各子進程並回收資源
18 void get_fds();
19 void get_status();    //獲取子進程狀態
20 
21 int main(int argc, const char *argv[])
22 {
23     key = ftok(".", 345);
24     if(key < 0){
25         perror("ftok failed");
26         return -errno;
27     }
28 
29     msqid = msgget(key, IPC_CREAT|IPC_EXCL|0664);
30     if(msqid <= 0){
31         if(errno == EEXIST){
32             msqid = msgget(key, 0664);
33         }else{
34             perror("msgget failed\n");
35             return -errno;
36         }
37     }
38 
39     for(i = 1; i < 6; i++){
40         pid[i] = fork();
41         if(pid[i] < 0){
42             perror("fork failed\n");
43             return -errno;
44         }else if(pid[i] == 0){
45             msgrcv(msqid, &msg, sizeof(msg), i, 0);
46             signal(SIGUSR1, send_running_time);
47             while(1);
48         }else
49             ;
50     }
51 
52     signal(SIGINT, recycle_child);
53     while(1){
54         get_fds();
55         printf("*******Num && cmd*********\n");
56         scanf("%d,%d",&num, &cmd);
57         msg.mtype = num;
58         msg.mcmd  = cmd;
59         switch(cmd){
60         case 1:
61             msgsnd(msqid, &msg, sizeof(msg), 0);
62             printf("No.%d is start off running!\n", num);
63             break;
64         case 2:
65             kill(pid[num], SIGUSR1);
66             recv_running_time();
67             break;
68         case 3:
69             kill(pid[num], SIGTSTP);
70             sleep(1);
71             get_status();
72             break;
73         default:
74             perror("invalid cmd");
75             break;
76         }
77     }
78     return 0;
79 }
主函數
 1 void send_running_time(int arg)
 2 {
 3     msg.mtv = clock();
 4     msgsnd(msqid, &msg, sizeof(msg), 0);
 5 }
 6 
 7 void recv_running_time()
 8 {
 9     msgrcv(msqid, &msg, sizeof(msg), num, 0);
10     printf("No.%ld  has run %ld ms\n",msg.mtype, msg.mtv/1000);
11 }
12 
13 void recycle_child(int arg)
14 {
15     for(i = 1; i < 6; i++){
16         kill(SIGKILL, pid[i]);
17         waitpid(pid[i], &status, WNOHANG );
18     }
19     exit(0);
20 }
21 
22 void get_fds()
23 {
24     for(i = 1; i < 6; i++){
25         sprintf(dir,"/proc/%d/status",pid[i]);
26         fd[i] = open(dir,O_RDONLY); 
27     }
28 }
29 
30 void get_status()
31 {
32     for(i = 1; i < 6; i++){
33         read(fd[i], dir, sizeof(dir));
34         p = strtok(dir, "\n");
35         p = strtok(NULL, "\n");
36         printf("No.%d\t%s\n",i, p);
37     }
38 }
子函數

 

TIPS:   code

  • 子進程會對父進程的.data和.bss段精準複製,父進程在fork各子進程時,全局變量 i 的值均不一樣,因此 i 能夠做爲子進程中msgrcv()的long mtype值。
  • 使用for循環fork()子程序時留心遞歸建立。   
  • 子進程在while(1)時可接收signal並做相應處理。   
  • 重載Ctrl+c,使其結束父進程時殺死各子進程並回收資源(recycle_child())。  
  • open("/proc/pid/status/",O_RDONLY)可查看對應進程的狀態(get_status())。
  • clock()函數得到進程running態時間,而不計sleeping等其餘態時間。
相關文章
相關標籤/搜索