System V IPC对象 共享内存、消息队列、信号灯集(6.7)
来源:互联网 发布:java zip压缩 编辑:程序博客网 时间:2024/05/19 11:49
System V IPC对象 共享内存、消息队列、信号灯集
原理:
进程都是通过IPC对象唯一的名字,称为键key,找到IPC对象,但内核还是通过IPC对象的ID来找到它.
不同进程只要获得同一IPC对象的键key,就可以实现操作同一IPC对象,从而实际进程间通信
----------------------------------------------------------
key_t ftok(const char *pathname, int proj_id);
功能:获得key值
参数:
pathname 一个已经存在的文件路径,(避免传".")
proj_id 只会使用它的低八位
----------------------------------------------------------
例:
key_t key = ftok("/home/will/",'i');
一 共享内存
1.申请一块共享内存
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:申请一块指定大小共享内存
参数:
key
获得key方法:
a.IPC_PRIVATE : 在亲缘间进程通信使用
b.ftok()函数获得key :可用于非亲缘关系的进程间
size 申请的大小,(分配的实际大小是4K的倍数,但可用的大小为申请大小)
shmflg :
IPC_CREAT | 0666 对应的共享内存段不存在,则创建, 存在直接返回ID
IPC_CREAT | IPC_EXCL | 0666
如果对应的共享内存段已经存在,此时shmget调用失败,错误码设为EEXIST
返回值: 成功返回共享内存id;失败返回-1
注意:
当key值对应的共享内存ID不存在,此时会申请一块新的共享内存区域
当key值对应的共享内存ID存在,此时直接返回已经存在的共享内存ID
---------------------------------------------------------------
查看IPC对象
ipcs -m/-q/-s
删除IPC对象
ipcrm -m/-q/-s ID
-m:memory
-q:queue
-s:semaphore
练习:探测共享内存是否存在,如果存在,报错,如果不存在,则创建
2.共享内存映射
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:映射共享内存到进程的私有地址空间
参数:
shmid 共享内存段的标识
shmaddr NULL 让系统自动完成映射
shmflg 0 映射可以读写;
SHM_RDONLY 映射后只能读
返回值:
成功返回映射后的地址;失败返回 (void *)-1,并置errno
注意:进程结束,映射自动撤销
3.撤销共享内存映射
int shmdt(const void *shmaddr);
返回值:成功返回0;失败返回-1,并置errno
注意给shmdt传的地址必须是shmat获得的!
4.删除共享内存
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:对共享内存进行控制
若cmd参数设置为IPC_RMID,可实现删除共享内存
注意:删除共享内存并不是只要有进程删除就立刻删除,
而是当映射次数为0时才会真正删除。
例:删除共享内存
shmctl(shmid,IPC_RMID,NULL);
二 消息队列
1.创建消息队列
int msgget(key_t key, int msgflg);
功能:创建消息队列
参数:
key IPC_PRIVATE 或 ftok()
msgflg IPC_CREAT | 0666 或 IPC_CREAT | IPC_EXCL | 0666
返回值:
成功返回ID,失败返回-1
2.发送消息
//封装消息结构体
typedef struct
{
//第一个字段必须是消息类型
long type;
//正文部分
...
}msg_t;
//消息正文大小
#define MSG_LEN (sizeof(msg_t) - sizeof(long))
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向消息队列中添加消息
参数:
msqid 消息队列的ID
msgp 消息存放的地址
msgsz 消息正文的大小--- sizeof(msg_t) - sizeof(long)
msgflg
0:阻塞的方式发送消息
IPC_NOWAIT:非阻塞发送消息(当消息队列中没有可用空间时,不阻塞,立即返回一个错误码EAGAIN)
返回值:
成功返回0,失败返回-1
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
功能:接收指定类型的消息
参数:
msgid 消息队列ID
msgp 接收的消息存放的地址
msgsz 消息正文的大小
msgtyp 接收的消息的类型
msgflg 0(阻塞方式调用) 或 IPC_NOWAIT (没有指定类型消息,不阻塞,立即返回)
返回值:
成功返回接收正文的大小,失败返回-1
例如:接收消息类型为100的消息
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:对消息队列进行控制
若cmd参数设置为IPC_RMID,可实现立即删除消息队列
例:msgctl(msqid,IPC_RMID,NULL);
练习:通过消息队列让A终端上父子进程和B终端上子父进程聊天
要求一边输入quit,所有进程结束.
三 信号灯集
(1)创建一个信号灯集
int semget(key_t key, int nsems, int semflg);
功能:创建或获得信号灯集
参数:
key IPC_PRIVATE 或 ftok()
nsems 信号灯集中信号灯的个数(注意:信号灯的编号从0开始)
semflg IPC_CREAT | 0666 或 IPC_CREAT | IPC_EXCL | 0666
返回值:
成功返回id,失败返回-1
(2)初始化信号灯集中的信号灯的值
int semctl(int semid, int semnum, int cmd, .../*union semun arg*/);
功能:对信号灯集中信号灯进行控制
参数:
semid :信号灯集ID
semnum :操作的信号灯编号,注意信号灯集中的信号灯编号从0开始
cmd :控制命令 SETVAL:设置信号灯值 GETVAL:获得信号灯值 都需第四个共用体类型参数
IPC_RMID:立即删除信号灯集
arg :cmd参数中若指定SETVAL需要保存要设置的信号灯值,或GETVAL
例如:初始化信号灯集中0号信号灯的值为1
原理:
进程都是通过IPC对象唯一的名字,称为键key,找到IPC对象,但内核还是通过IPC对象的ID来找到它.
不同进程只要获得同一IPC对象的键key,就可以实现操作同一IPC对象,从而实际进程间通信
----------------------------------------------------------
key_t ftok(const char *pathname, int proj_id);
功能:获得key值
参数:
pathname 一个已经存在的文件路径,(避免传".")
proj_id 只会使用它的低八位
----------------------------------------------------------
例:
key_t key = ftok("/home/will/",'i');
一 共享内存
1.申请一块共享内存
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:申请一块指定大小共享内存
参数:
key
获得key方法:
a.IPC_PRIVATE : 在亲缘间进程通信使用
b.ftok()函数获得key :可用于非亲缘关系的进程间
size 申请的大小,(分配的实际大小是4K的倍数,但可用的大小为申请大小)
shmflg :
IPC_CREAT | 0666 对应的共享内存段不存在,则创建, 存在直接返回ID
IPC_CREAT | IPC_EXCL | 0666
如果对应的共享内存段已经存在,此时shmget调用失败,错误码设为EEXIST
返回值: 成功返回共享内存id;失败返回-1
注意:
当key值对应的共享内存ID不存在,此时会申请一块新的共享内存区域
当key值对应的共享内存ID存在,此时直接返回已经存在的共享内存ID
---------------------------------------------------------------
查看IPC对象
ipcs -m/-q/-s
删除IPC对象
ipcrm -m/-q/-s ID
-m:memory
-q:queue
-s:semaphore
练习:探测共享内存是否存在,如果存在,报错,如果不存在,则创建
2.共享内存映射
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:映射共享内存到进程的私有地址空间
参数:
shmid 共享内存段的标识
shmaddr NULL 让系统自动完成映射
shmflg 0 映射可以读写;
SHM_RDONLY 映射后只能读
返回值:
成功返回映射后的地址;失败返回 (void *)-1,并置errno
注意:进程结束,映射自动撤销
3.撤销共享内存映射
int shmdt(const void *shmaddr);
返回值:成功返回0;失败返回-1,并置errno
注意给shmdt传的地址必须是shmat获得的!
4.删除共享内存
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:对共享内存进行控制
若cmd参数设置为IPC_RMID,可实现删除共享内存
注意:删除共享内存并不是只要有进程删除就立刻删除,
而是当映射次数为0时才会真正删除。
例:删除共享内存
shmctl(shmid,IPC_RMID,NULL);
二 消息队列
1.创建消息队列
int msgget(key_t key, int msgflg);
功能:创建消息队列
参数:
key IPC_PRIVATE 或 ftok()
msgflg IPC_CREAT | 0666 或 IPC_CREAT | IPC_EXCL | 0666
返回值:
成功返回ID,失败返回-1
2.发送消息
//封装消息结构体
typedef struct
{
//第一个字段必须是消息类型
long type;
//正文部分
...
}msg_t;
//消息正文大小
#define MSG_LEN (sizeof(msg_t) - sizeof(long))
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向消息队列中添加消息
参数:
msqid 消息队列的ID
msgp 消息存放的地址
msgsz 消息正文的大小--- sizeof(msg_t) - sizeof(long)
msgflg
0:阻塞的方式发送消息
IPC_NOWAIT:非阻塞发送消息(当消息队列中没有可用空间时,不阻塞,立即返回一个错误码EAGAIN)
返回值:
成功返回0,失败返回-1
例如:发送消息类型是100,消息内容"hello world"
typedef struct {long type;char buf[1024];#if 0/*{{{*/ time_t t; pid_t pid;#endif/*}}}*/}msg_t;msg_t msg;msg_t *pmsg = (msg_t *)malloc(sizeof(msg_t));msg.type = 100;strcpy(msg.buf,"hello world");sprintf(msg.buf,"hello world");if(msgsnd(msgid,&msg,MSG_LEN,0) < 0){....}3.接收消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
功能:接收指定类型的消息
参数:
msgid 消息队列ID
msgp 接收的消息存放的地址
msgsz 消息正文的大小
msgtyp 接收的消息的类型
msgflg 0(阻塞方式调用) 或 IPC_NOWAIT (没有指定类型消息,不阻塞,立即返回)
返回值:
成功返回接收正文的大小,失败返回-1
例如:接收消息类型为100的消息
msg_t msg;if(msgrcv(msgid,&msg,MSG_LEN,100,0) < 0){.....}printf("------------------------------\n");printf("TYPE : %ld.\n",msg.type);printf("MTXT : %s.\n",msg.buf);printf("------------------------------\n");4.删除消息队列
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:对消息队列进行控制
若cmd参数设置为IPC_RMID,可实现立即删除消息队列
例:msgctl(msqid,IPC_RMID,NULL);
练习:通过消息队列让A终端上父子进程和B终端上子父进程聊天
要求一边输入quit,所有进程结束.
三 信号灯集
(1)创建一个信号灯集
int semget(key_t key, int nsems, int semflg);
功能:创建或获得信号灯集
参数:
key IPC_PRIVATE 或 ftok()
nsems 信号灯集中信号灯的个数(注意:信号灯的编号从0开始)
semflg IPC_CREAT | 0666 或 IPC_CREAT | IPC_EXCL | 0666
返回值:
成功返回id,失败返回-1
(2)初始化信号灯集中的信号灯的值
int semctl(int semid, int semnum, int cmd, .../*union semun arg*/);
功能:对信号灯集中信号灯进行控制
参数:
semid :信号灯集ID
semnum :操作的信号灯编号,注意信号灯集中的信号灯编号从0开始
cmd :控制命令 SETVAL:设置信号灯值 GETVAL:获得信号灯值 都需第四个共用体类型参数
IPC_RMID:立即删除信号灯集
arg :cmd参数中若指定SETVAL需要保存要设置的信号灯值,或GETVAL
例如:初始化信号灯集中0号信号灯的值为1
union semun { intval;/* Value for SETVAL */ struct semid_ds *buf;/* Buffer for IPC_STAT, IPC_SET */ unsigned short *array;/* Array for GETALL, SETALL */ struct seminfo *__buf;/* Buffer for IPC_INFO(Linux-specific) */};union semun sem_val;sem_val.val = 1;if(semctl(semid,0,SETVAL,sem_val) < 0){...}(3)封装p/v操作
int semop(int semid, struct sembuf *sops, unsigned nsops);//参数: semid 信号灯集id sopsstruct sembuf //其中部分成员{ //操作信号灯集中信号灯序号 unsigned short sem_num; /* semaphore number */ //sem_op -1:p操作 1:v操作 0:等待 short sem_op; /* semaphore operation */ //0:阻塞 IPC_NOWAIT:非阻塞 SEM_UNDO:进程结束的时候若未释放共享资源,由内核释放申请的资源 short sem_flg; /* operation flags */} nsops 操作的信号灯个数 //->p操作:// 信号灯集的id 操作具体的信号灯编号(从0开始)void P(int semid, int s_num){struct sembuf sem;sem.sem_num = s_num;sem.sem_op = -1;/*sem.sem_flg = 0;*/ sem.sem_flg = SEM_UNDO;if(semop(semid,&sem,1) < 0){perror("fail to semop");exit(EXIT_FAILURE);}return;}//->v操作:// 操作信号灯集中信号灯序号void V(int semid,int s_num){struct sembuf sem;sem.sem_num = s_num;sem.sem_op = 1;sem.sem_flg = SEM_UNDO;if(semop(semid,&sem,1) < 0){perror("fail to semop");exit(EXIT_FAILURE);}return;}(4)删除信号灯集
int semctl(int semid, int semnum, int cmd, ...);//如果cmd是IPC_RMID,不需要第四个参数if(semctl(semid,0,IPC_RMID) < 0){perror("fail to semctl");exit(exit_failure);}
0 0
- System V IPC对象 共享内存、消息队列、信号灯集(6.7)
- linux system V IPC 信号灯和共享内存实例
- 进程间同步---system v ipc 对象信号灯集
- 进程间同步---system v ipc 对象信号灯集
- 进程间同步---system v ipc 对象信号灯集
- 进程间同步---system v ipc 对象信号灯集
- 进程间同步---system v ipc 对象信号灯集
- Linux IPC(进程间通信)摘要(信号灯,共享内存,消息队列,管道)(一)
- linux基础编程:进程通信之System V IPC:消息队列,信号量,共享内存
- linux基础编程:进程通信之System V IPC:消息队列,信号量,共享内存
- 消息队列(system V IPC)
- IPC对象、共享内存和消息队列
- 共享内存(system V IPC)
- System V IPC共享内存
- linux 进程间通信(system v 信号灯+system v 共享内存)实例
- IPC之System V 消息队列 (代码实现)
- 【记录】system v ipc(2) 消息队列
- 细说linux IPC(十):system V 消息队列
- Android中Toast不显示的解决方案
- postfix和dovecot的邮件认证及加密
- jdk6,jdk7直链下载方法
- Linux 设备模型之(总线、设备和驱动程序)(三)
- 浅析final finally finalize
- System V IPC对象 共享内存、消息队列、信号灯集(6.7)
- 项目中使用Quartz集群分享
- Quartz 有状态的JobDataMap
- Quartz之JobExecutionException
- amanda安装
- android.os.NetworkOnMainThreadException
- 开源业务规则引擎JBoss Drools入门介绍
- drools规则语法(一)
- 文件的输入输出