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等其他态时间。
时间: 2024-10-28 11:18:05

Linux下进程间通信(嵌入式面试题)的相关文章

Linux下进程间通信之命名管道(FIFO)

匿名管道的一个不足之处是没有名字,因此,只能用于具有亲缘关系的进程间通信.在命名管道(FIFO)提出后,该限制得到了克服.FIFO不同于pipe在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中.命名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够相互通信. FIFO总是按照先进先出的原则工作,第一个被写入的数据将首先从管道中读出. Linux下有两种方式创建FIFO,一是在shell下交互的建立一个命名管道,二是在程序中使用系统函

【操作系统之三】Linux下进程间通信-IPC(Inter-Process Communication)

管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信:信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身:linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够

在linux下使用嵌入式qt

步骤 1 在linux下编译安装arm-qte-4.8.5 2 修改配置文件,设置qte的路径 vim /etc/profile export QTDIR=自己的qt安装目录 export PATH=$QTDIR/bin:$PATH export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH vim /etc/bashrc 同上 3 在qt-creater中生成一个qt工程,拷贝到linux系统 4 在工程目录执行qmake命令,生成makefile文件

linux下进程间通信IPC几种方式性能比较

在项目中,经常会遇到单机上进程间的通信,常用的进程间通信方式一般有以下几种 1 socket 2 unixsocket 3 共享内存(share-memory) 4 管道(pipe) 5 消息队列(message-queue) 6 文件(file) 7 消息总线(比如zeromq) 8 其他中间件(比如redis, memchache, 数据库等) 如果项目仅仅是消息的传递,对性能要求不高,则以上每种方式都可以实现进程间通信,我们可以选择较容易实现的方式来运用. 如果项目对消息传递性能要求很高,

Linux下进程间通信之消息队列

消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.每个数据块都被认为是一个有类型,接受者进程接受的数据块可以有不同的类型值.我们可以通过发送消息来避免命名管道的同步和阻塞问题.消息队列是基于消息的,且消息队列的读取不一定是先入先出.每个消息的最大长度是有上限的,每个消息队列总的字节数是有上限的,系统上消息队列的总数也有一个上限. 具体步骤如下: 1):创建新消息队列或取得已存在消息队列 2):向队列读.写消息 3):设置消息队列属性 comm.h comm.c sever.c cli

Linux下进程间通信的方法--信号量

这里的信号量主要是在不同的进程之间使用. 需要四个操作 P操作 V操作 以及通过semctl调用command参数设置SETVAL来初始化信号量,在使用信号量之前必须要这么做. 并且可以通过semctl调用command设置为IPC_RMID来删除信号量ID: 因为库里没有定义union semun,因此需要自己定义. 用到信号量的三个函数 semget 用来创建一个新信号量或者取得一个已有信号量的键 semop 用来改变信号量的值 semctl 用来直接控制信号量信息,比如semop之前必须先

Linux下进程间通信之共享内存

共享内存便是在内存里申请一块空间,这块空间可以有多个进程拥有,其申请的空间必须是4096的整数倍,可以读写数据,其效率是system V 版本中几种通信方式间最高效的,但它的同步与互斥需要自己来维护,因此其常与信号量结合起来使用. 下面是一个简单的实现: shm.h shm.c 测试函数: 运行结果:

【网络编程基础】Linux下进程通信方式(共享内存,管道,消息队列,Socket)

在网络课程中,有讲到Socket编程,对于tcp讲解的环节,为了加深理解,自己写了Linux下进程Socket通信,在学习的过程中,又接触到了其它的几种方式.记录一下. 管道通信(匿名,有名) 管道通信,在一个进程之中,只能单一的对其写或者是读,而不可以及执行写操作又执行读操作.这一点,我们可以将其想象成我们的水管,分别连着不同的两端,在有水流的时候,一端只能进行输入,另一端只能进行输出,而不可以同时输入和输出. 管道又分为有名管道和匿名管道,两者的区别在于对于匿名管道,其只能在具有亲缘关系的父

linux下六大IPC机制【转】

转自http://blog.sina.com.cn/s/blog_587c016a0100nfeq.html linux下进程间通信IPC的几种主要手段简介: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信:信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身:linux除了支持Un