嵌入式开发记录 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 }

浙公网安备 33010602011771号