嵌入式开发记录 day15 进程间通信 消息队列

1、消息队列常用的函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);    // 发送消息,相当于写文件操作write()
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);  // 接收消息,相当于读文件操作read
int msgget(key_t key, int msgflg); // 获取消息队列,相当于打开文件open(),创建消息队列
int msgctl(int msqid, int cmd, struct msqid_ds *buf); // 删除消息队列
// 所用到的结构体 struct msgbuf { long mtype; // message type, must be > 0 char mtext[1]; // message data };

2、给消息队列发送信息msgsnd.c

 1 #include <sys/types.h>
 2 #include <sys/ipc.h>
 3 #include <sys/msg.h>
 4 #include <errno.h>
 5 #include <stdio.h>
 6 #include <stdlib.h>
 7 #include <string.h>
 8 
 9 #define MAX_TEXT  512 
10 
11 struct msg_st
12 {
13     long int msg_type;
14     char text[MAX_TEXT];
15 };
16 
17 
18 int main()
19 {
20     struct msg_st data;
21     char buf[BUFSIZ];   // 常量
22     int msgid = -1;
23     int running = 1;
24     msgid = msgget((key_t)1234,0666|IPC_CREAT);  // 创建一个消息队列ID号为1234的消息队列
25     if(msgid == -1){ 
26         fprintf(stderr,"msgget failed with error:%d\n ",errno);
27         exit(EXIT_FAILURE);
28     }
29     
30     while(running){
31         printf("Enter some text:");
32         fgets(buf,BUFSIZ,stdin);     // 从键盘获取输入
33         data.msg_type  =1;              // 标志位 发送数据
34         stpcpy(data.text,buf);       // 拷贝文本
35         if(msgsnd(msgid,(void*)&data,MAX_TEXT,0) == -1){
36             fprintf(stderr,"msgsnd failed \n");
37             exit(EXIT_FAILURE);
38         }
39         if(strncmp(buf,"end",3) == 0){  // 比较输入 输入end结束
40             running = 0;
41         }
42         sleep(1);
43     }
44     exit(EXIT_SUCCESS);
45 }

3、接收消息队列信息msgrcv()

 1 #include <sys/types.h>
 2 #include <sys/ipc.h>
 3 #include <sys/msg.h>
 4 #include <errno.h>
 5 #include <stdio.h>
 6 #include <stdlib.h>
 7 #include <string.h>
 8 
 9 #define MAX_TEXT  512 
10 
11 struct msg_st
12 {
13     long int msg_type;
14     char text[MAX_TEXT];
15 };
16 
17 int main()
18 {
19     struct msg_st data;
20     char buf[BUFSIZ];   // 常量
21     int msgid = -1;
22     int running = 1;
23     long int msgtype = 0;
24     
25     msgid = msgget((key_t)1234,0666|IPC_CREAT); // 创建消息队列
26     if(msgid == -1){ 
27         fprintf(stderr,"msgget failed with error:%d\n ",errno);
28         exit(EXIT_FAILURE);
29     }
30     // 从队列中获取消息
31     while(running){
32         if(msgrcv(msgid,(void*)&data,BUFSIZ,msgtype,0) == 0){
33             fprintf(stderr,"msgrcv failed with %d\n",errno);
34             exit(EXIT_FAILURE);
35         }
36         // 从消息队列中接收到的数据打印出来
37         printf("you wrote :%s\n",data.text);
38         if(strncmp(data.text,"end",3)== 0){
39             running = 0;
40         }
41     }
42     // 关闭消息队列
43     if(msgctl(msgid,IPC_RMID,0)){
44         fprintf(stderr,"msgctl failed \n");
45         exit(EXIT_FAILURE);
46     }
47     exit(EXIT_SUCCESS);
48 }

4、信号相关的方法

//alarm - set an alarm clock for delivery of a signal
#include <unistd.h>
unsigned int alarm(unsigned int seconds);

 // signal - ANSI C signal handling
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
/*
驱动应用比较多;
SIGALRAM:闹钟
SIGHUP: 终端发出的结束信号
SIGINT:键盘的ctrl+z
SIGKILL:kill 命令产生的信号
SIGSTOP:键盘ctrl+z
pause:暂停当前进程,等待信号到来继续运行
*/
// man 2 sigaction 
int sigaction(int signum, const struct sigaction *act,
                     struct sigaction *oldact);
 struct sigaction {
               void     (*sa_handler)(int);
               void     (*sa_sigaction)(int, siginfo_t *, void *);
               sigset_t   sa_mask;
               int        sa_flags;
               void     (*sa_restorer)(void);
           };

5、发送信号 sighandle()

 1 #include <signal.h>
 2 #include <stdio.h>
 3 #include <unistd.h>
 4 
 5 void handler()
 6 {
 7     printf("hello signal\n");
 8 }
 9 
10 int main()
11 {
12     int i;
13     signal(SIGALRM,handler);
14     alarm(5); //  5s以后产生信号
15     for(i = 0;i<7;i++)
16     {
17         printf("sleep %d ....\n",i);
18         sleep(1);
19     }
20     return 0;
21 }

6、信号集

 1 #include <signal.h>
 2 #include <stdio.h>
 3 #include <unistd.h>
 4 #include <stdlib.h>
 5 
 6 void handler(int sig)
 7 {
 8     printf("hello signal: %d\n",sig);
 9 }
10 
11 int main()
12 {
13     // 使用信号集
14     // 初始化信号集
15     sigset_t sigset; // 记录屏蔽字
16     sigset_t ign;    // 记录被阻塞的信号集
17     struct sigaction act;
18     // 清空信号集
19     sigemptyset(&sigset);
20     sigemptyset(&ign);
21     
22     // 向信号集添加信号
23     sigaddset(&sigset,SIGINT);
24     
25     // 设置处理函数和信号集
26     act.sa_handler = handler;
27     sigemptyset(&act.sa_mask);
28     act.sa_flags = 0;
29     sigaction(SIGINT,&act,0);
30     
31     // 等待信号
32     printf("wait signal SIGINT\n");
33     pause(); //  挂起进程等待信号
34     
35     // 设置进程屏蔽字
36     sigprocmask(SIG_SETMASK,&sigset,0);
37     printf("Please press Ctrl + c in 10 s\n");
38     sleep(10);
39     // 测试SIGINT是否被屏蔽
40     sigpending(&ign);
41     // 测试是否加入了信号集
42     if(sigismember(&sigset,SIGINT)){
43         printf("the SIGINT signal has ignored\n");
44     }
45     
46     // 在信号集中删除信号
47     sigdelset(&sigset,SIGINT);
48     printf("Wait the signal SIGINT delete\n");
49     
50     // 将进程的屏蔽字重新设置 取消对SIGINT的设置
51     // 挂起进程等待信号sigsuspend()
52     sigsuspend(&sigset);
53     printf("the app exit in 5 second \n");
54     sleep(5);
55     exit(0);
56     return 0;
57 }

7、信号量  典型应用共享内存访问控制

// 信号量常用的函数
#include <sys/ipc.h>
#include <sys/shm.h>

// 分配一块共享内存区域 返回内存的ID号码
int shmget(key_t key, size_t size, int shmflg);   

// shared memory operations
void *shmat(int shmid, const void *shmaddr, int shmflg);

int shmdt(const void *shmaddr);

8、向共享内存写操作shmwrite.c

 1 #include <unistd.h>  
 2 #include <stdlib.h>  
 3 #include <stdio.h>  
 4 #include <string.h>  
 5 #include <sys/shm.h>  
 6 
 7   
 8 #define TEXT_SZ 2048  
 9   
10 struct shared_use_st  
11 {  
12     //作为一个标志,非0:表示可读,0表示可写
13     int written;
14     //记录写入和读取的文本    
15     char text[TEXT_SZ];  
16 };    
17   
18 int main(void)  
19 {  
20     int running = 1;  
21     void *shm = NULL;  
22     struct shared_use_st *shared = NULL;  
23     char buffer[BUFSIZ + 1];//用于保存输入的文本  
24     int shmid;  
25     //创建共享内存  
26     shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);  
27     if(shmid == -1)  
28     {  
29         fprintf(stderr, "shmget failed\n");  
30         exit(EXIT_FAILURE);  
31     }  
32     //将共享内存连接到当前进程的地址空间  
33     shm = shmat(shmid, (void*)0, 0);  
34     if(shm == (void*)-1)  
35     {  
36         fprintf(stderr, "shmat failed\n");  
37         exit(EXIT_FAILURE);  
38     }  
39     printf("Memory attached at %p\n", shm);  
40     //设置共享内存  
41     shared = (struct shared_use_st*)shm;  
42     while(running)//向共享内存中写数据  
43     {  
44         //数据还没有被读取,则等待数据被读取,不能向共享内存中写入文本  
45         while(shared->written == 1)  
46         {  
47             sleep(1);  
48             printf("Waiting...\n");  
49         }  
50         //向共享内存中写入数据  
51         printf("Enter some text: ");  
52         fgets(buffer, BUFSIZ, stdin);  
53         strncpy(shared->text, buffer, TEXT_SZ);  
54         //写完数据,设置written使共享内存段可读  
55         shared->written = 1;  
56         //输入了end,退出循环(程序)  
57         if(strncmp(buffer, "end", 3) == 0)  
58             running = 0;  
59     }  
60     //把共享内存从当前进程中分离  
61     if(shmdt(shm) == -1)  
62     {  
63         fprintf(stderr, "shmdt failed\n");  
64         exit(EXIT_FAILURE);  
65     }  
66     sleep(2);  
67     exit(EXIT_SUCCESS);  
68 }

9、从共享内存读操作shmread.c

 1 #include <unistd.h>  
 2 #include <stdlib.h>  
 3 #include <stdio.h>  
 4 #include <sys/shm.h>  
 5   
 6 #define TEXT_SZ 2048  
 7   
 8 struct shared_use_st  
 9 {  
10     //作为一个标志,非0:表示可读,0表示可写
11     int written;
12     //记录写入和读取的文本    
13     char text[TEXT_SZ];  
14 };  
15   
16 int main(void)  
17 {  
18     int running = 1;//程序是否继续运行的标志  
19     void *shm = NULL;//分配的共享内存的原始首地址  
20     struct shared_use_st *shared;//指向shm  
21     int shmid;//共享内存标识符  
22     
23     //1、创建共享内存  
24     shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);  
25     if(shmid == -1)  
26     {  
27         fprintf(stderr, "shmget failed\n");  
28         exit(EXIT_FAILURE);  
29     }  
30     //2、将共享内存连接到当前进程的地址空间  
31     shm = shmat(shmid, 0, 0);  
32     if(shm == (void*)-1)  
33     {  
34         fprintf(stderr, "shmat failed\n");  
35         exit(EXIT_FAILURE);  
36     }  
37     printf("\nMemory attached at %p\n", shm);  
38     //设置共享内存  
39     shared = (struct shared_use_st*)shm;  
40     shared->written = 0;  
41     while(running)//读取共享内存中的数据  
42     {  
43         //没有进程向共享内存定数据有数据可读取  
44         if(shared->written != 0)  
45         {  
46             printf("You wrote: %s", shared->text);  
47             sleep(rand() % 3);  
48             //读取完数据,设置written使共享内存段可写  
49             shared->written = 0;  
50             //输入了end,退出循环(程序)  
51             if(strncmp(shared->text, "end", 3) == 0)  
52                 running = 0;  
53         }  
54         else//有其他进程在写数据,不能读取数据  
55             sleep(1);  
56     }  
57     //3、把共享内存从当前进程中分离  
58     if(shmdt(shm) == -1)  
59     {  
60         fprintf(stderr, "shmdt failed\n");  
61         exit(EXIT_FAILURE);  
62     }  
63     //4、删除共享内存  
64     if(shmctl(shmid, IPC_RMID, 0) == -1)  
65     {  
66         fprintf(stderr, "shmctl(IPC_RMID) failed\n");  
67         exit(EXIT_FAILURE);  
68     }  
69     exit(EXIT_SUCCESS);  
70 }

 

posted @ 2020-06-25 17:26  笑不出花的旦旦  阅读(267)  评论(0)    收藏  举报