Linux下进程间通信(嵌入式面试题)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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].time和msg[num.]status即可。
多进程:每个队员匹配一个进程。子进程睡眠态-->状态1,运行态-->状态2,暂停态-->状态3. 而进程间通信我们选用消息队列和信号的方法:
子进程被创建之后,因msgrcv()而处于阻塞态(即睡眠态)。接收到特定msg,便进入运行态while(1)。接收SIGUSR1信号时,将运行时间发送给父进程。接收到SIGSTOP信号时进入暂停态,且父进程中获取各子程序的状态。
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:
- 子进程会对父进程的.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等其他态时间。
以上是关于Linux下进程间通信(嵌入式面试题)的主要内容,如果未能解决你的问题,请参考以下文章