13--信号量,共享内存和消息队列
来源:互联网 发布:敏捷软件开发 pdf 编辑:程序博客网 时间:2024/05/22 20:40
进程间的通信:
(1) 基于文件的通信:
1. 普通文件(io/mmap)
2.有名管道文件
3.匿名管道文件
4.socket
(2)基于内存的通信:
1.信号量 :用于管理对资源的访问。
2.共享内存:用于进程之间高校的地共享数据。
3.消息队列:在程序之间传递数据的一种简单方法。
使用到的命命令:
—————————————————————————
$ ipcs
$ ipcs -s --------- 查看信号量
$ ipcs -m ---------- 共享内存
$ ipcs -q ----------- 消息队列
$ ipcrm -q 编号ID ---------删除消息队列
——————————————————————————
一.信号量
1.semget函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, /// 为一个整数值,
int nsems, //// 为信号量数目,通常取值为1.
int semflg);/// 一组标志,通常使用 IPC_CREAT | IPC_EXCL 来创建新的,唯一的信号量。
说明:创建一个信号量,获得一个信号量ID。
如果成功:
返回信号量标识符。
如果失败:
返回-1.
2. semop函数
int semop(int semid, //// 有semget返回的信号量标识符。
struct sembuf *sops, ////指向结构体数组的指针
unsigned nsops); ///
说明: 用于改变信号量的值
第二个参数指向的结构体数组中,每个数组元素至少包含以下成员
struct sembuf
{
unsigned short sem_num; /* semaphore number */ 信号编号,除非使用一组信号,否则一般为0
short sem_op; /* semaphore operation */信号操作,一般有两种取值:-1(p操作,等待信号变为可用); +1(v操作,发送信号表示信号量现在已可用)
short sem_flg; /* operation flags */通常设置为SEM_UNDO,
};
3. semctl 函数
int semctl(int semid, ///有semget返回的信号量标识符
int semnum, /// 信号量编号,一般取值为0(表示是唯一信号量)
int cmd, ...); /// 采取的行动
说明: 直接控制信号量信息。
cmd有两个最常用的值:
SETVAL: 用来把信号量初始化为一个已知的值。
IPC_RMID: 用于删除一个已知无需继续使用的信号量标识符。
二.共享内存
1.shmget函数
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, /// ftok 函数可以取得唯一的key值
size_t size, /// 共享内存容量
int shmflg);/// 9个比特的权限标志
说明: 创建共享内存,返回共享内存标识符。
第三个参数的常见两种方式:
创建: (IPC_CREAT | IPC_EXCL)
打开: 0
2.shmat 函数
void *shmat(int shmid,/// 由shmget返回的共享内存标识符。
const void *shmaddr, ///
int shmflg);
说明: 根据ID得到共享,访问内存数据。
3.shmdt函数
int shmdt(const void *shmaddr);
说明: 将共享内存从当前进程中分离,参数为shmat返回的地址指针。
4. shmctl 函数
int shmctl(int shmid, /// shmget返回的共享内存标识符
int cmd, /// 要采取的动作
struct shmid_ds *buf); /// 指向包含共享内存模式和访问权限的当前关联值
第二个参数cmd的可取值:
————————————————————————————
IPC_STAT ------
IPC_SET ------
IPC_RMID --------删除共享内存段
第三个参数的struct shmid_ds 结构体:
——————————————————————————————————
struct shmid_ds {
struct ipc_perm shm_perm; /* Ownership and permissions */
size_t shm_segsz; /* Size of segment (bytes) */
time_t shm_atime; /* Last attach time */
time_t shm_dtime; /* Last detach time */
time_t shm_ctime; /* Last change time */
pid_t shm_cpid; /* PID of creator */
pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */
shmatt_t shm_nattch; /* No. of current attaches */
...
};
——————————————————————————————————————
编程模型:
(1) 创建共享内存,得到一个ID;
(2)把ID映射成虚拟地址(挂载);
(3)使用虚拟地址访问内核共享内存
(4)卸载(分离)虚拟地址, shmdt
(5) 删除共享内存 shctl(修改/获取共享内存的属性)
案例:
shmA.c
/// shmA.c#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <sys/shm.h>#include <sys/ipc.h>key_t key;int shmid;int *p;int i = 0;void deal(int s){if(s==SIGINT){//4.卸载共享内存shmdtshmdt(p);//5.删除共享内存shctlshmctl(shmid,IPC_RMID,0);exit(0);}}main(){signal(SIGINT,deal);//1.创建共享内存, shmgetkey = ftok("/tmp",255);if(key == -1) printf("ftok error:%m\n"),exit(-1);shmid = shmget(key,4,IPC_CREAT | IPC_EXCL |0666);if(shmid == -1) printf("get error:%m\n"),exit(-1);//2.挂载共享内存shmatp = shmat(shmid,0,0);if(p == (int*)-1) printf("get error:%m\n"),exit(-1);//3.访问共享内存while(1){*p = i;sleep(1);++i;}}
shmB.c
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <sys/shm.h>#include <sys/ipc.h>key_t key;int shmid;int *p;void deal(int s){if(s==SIGINT){//4. 卸载共享内存, shmdtshmdt(p);exit(0);}}main(){signal(SIGINT,deal);//1.创建共享内存key = ftok("/tmp",255);if(key == -1) printf("ftok error:%m\n"),exit(-1);shmid = shmget(key,4,0);if(shmid == -1) printf("get error:%m\n"),exit(-1);//2.挂载共享内存shmatp = shmat(shmid,0,0);if(p == (int*)-1) printf("ar error:%m\n"),exit(-1);//3.访问共享内存while(1){sleep(1);printf("%d\n",*p);}}
补充:
——————————————————
$ ipcs -m ------ 查看共享内存
$ ipcrm -m 555****(文件ID) ------ 删除共享内存(这个文件ID是随机的)
三. 消息队列
消息队列是在两个不相关进程之间传递数据的,优势是独立于发送和接收进程而存在。
1. msgget函数-----------------创建消息队列函数
int msgget(key_t key, int msgflg);
2. msgsnd函数-------------------发送消息
int msgsnd(int msqid, //// 消息队列标识符
const void *msgp, /// 要发送的消息
size_t msgsz, //// 消息的长度
int msgflg); ///// 发送消息的方式,建议为0
3.msgrcv函数 ---------------从消息队列中获取消息
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
4.msgctl 函数
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
编程模型:
创建消息队列
使用消息队列
删除队列
//// msgA.c 发射部分#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <sys/msg.h>#define MAX_TEXT 512struct msgbuf{long mtype;char mtext[MAX_TEXT];};int main(){int flag = 1;key_t key;struct msgbuf msg;int msgid;char buffer[BUFSIZ];// 1.创建消息队列key = ftok(".",200);if(key == -1) printf("frok err:%m\n"),exit(-1);printf("key=%d\n",key);msgid = msgget(key,0666 | IPC_CREAT);if(msgid == -1) printf("msgget err:%m\n"),exit(-1);while(flag){printf("请输入您要发送的字符串(以“#”结束输入):\n");fgets(buffer,BUFSIZ,stdin);msg.mtype = 1;bzero(msg.mtext,sizeof(msg.mtext));strcpy(msg.mtext,buffer);if(msgsnd(msgid,&msg,MAX_TEXT,0) == -1) printf("msgsnd err:%m\n") ,exit(-1);if(strncmp(buffer,"#",1) == 0)flag = 0;}msgctl(msgid,IPC_RMID,0); // 删除队列exit(0);}
//// msgB.c 接收部分#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <sys/msg.h>struct msgbuf{long mtype;char mtext[BUFSIZ];};int main(){int flag = 1;key_t key;int msgid;struct msgbuf msg;key = ftok(".",200);if(key == -1) printf("ftok err:%m\n"),exit(-1);printf("key=%d\n",key);msgid = msgget(key,0666 | IPC_CREAT);if(msgid == -1) printf("msgget err:%m\n"),exit(-1);while(flag){bzero(msg.mtext,sizeof(msg.mtext));if(msgrcv(msgid,(void *)&msg,BUFSIZ,0,0) == -1) printf("msgrcv err:%m\n"),exit(-1);printf("你接收到的数据是:%s\n",msg.mtext);if(strncmp(msg.mtext,"#",1) ==0 )flag = 0;}// 删除消息队列msgctl(msgid,IPC_RMID,0); }
- 13--信号量,共享内存和消息队列
- Linux信号量 共享内存和消息队列
- linux 信号量、共享内存、和消息队列
- 信号量、消息队列和共享内存
- 信号量,共享内存和消息队列
- (十三) 信号量、消息队列和共享内存
- (十三) 信号量、消息队列和共享内存
- 信号量、共享内存和消息队列
- 17. 信号量,共享内存和消息队列
- 信号量 消息队列 共享内存
- 信号量、消息队列、共享内存
- Linux 消息队列、共享内存、信号量(二)共享内存和信号量
- Linux程序设计——信号量、共享内存和消息队列
- 《第 14 章》 信号量,共享内存和消息队列
- [Linux] 第 14 章 信号量,共享内存和消息队列
- 《Linux程序设计》——信号量、共享内存和消息队列
- IPC通信之消息队列、信号量和共享内存
- 第十四章 信号量,共享内存和消息队列
- iOS框架研究 之 UIResponder 可以接收事件的对象
- MySQL索引类型一览 让MySQL高效运行起来
- 互联网,将从内部颠覆企业管理模式
- Linux 简单常用指令(含绝招)
- 实例详解tomcat组件安装+Nginx反向代理tomcat+Apache使用mod_jk和mod_proxy反向代理和负载均衡
- 13--信号量,共享内存和消息队列
- 子曰不在词
- 【android 开发知识积累】——属性(Attribute)资源的使用和自定义View组件
- Failed to load the JNI shared library
- String 类
- DoubleKeyMap_实现
- Minimum Path Sum
- OK6410(s3c6410)存储方式之NAND FLASH
- javascript正则表达式