文章目录
sys/ipc.h
ftok()
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname,int proj_id);
功能:
生成供系统建立IPC通讯 (消息队列、信号量和共享内存) 时必须指定的ID值
参数:
pathname : 文件路径名
proj_id : 序列号,8 bit 的 id 整数,取值范围0~255
函数返回值:
成功: 返回合成的 key
失败 : -1,并设置 errno
key 由 文件的 inode 节点号 与 proj_id 构成
- inode 节点号 :每个存在的文件操作系统都会有唯一的编号,可通过 ls -i 命令查看
sys/msg.h 消息队列
msgget()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key,int msgflg);
参数:
key : 由ftok()函数合成
msgflg : 消息队列标志 (多个参数用|连接)
IPC_CREAT : 创建消息队列
IPC_EXCL : 和IPC_CREAT一起使用,若消息队列存在,则报错,并设置errno为EEXIST
文件权限标志 : 如0644
返回值:
成功 : 返回 消息队列id
失败 : 返回 -1,并设置errno
msgctl()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid,int cmd,struct msqid_ds *buf);
参数 :
msqid : 消息队列id
cmd : 命令字
IPC_STAT : 获取消息队列属性
IPC_SET : 设置消息队列属性
IPC_RMID : 删除消息队列,用此命令字时,第三个参数为NULL
buf : 消息队列属性结构体对象指针
返回值 :
成功 : IPC_STAT,IPC_SET and IPC_RMID 返回 0
失败 : 返回 -1,并设置errno
消息队列属性结构体定义如下:
struct msqid_ds {
struct ipc_perm msg_perm; /* Ownership and permissions */
time_t msg_stime; /* Time of last msgsnd(2) */
time_t msg_rtime; /* Time of last msgrcv(2) */
time_t msg_ctime; /* Time of creation or last
modification by msgctl() */
unsigned long msg_cbytes; /* # of bytes in queue */
msgqnum_t msg_qnum; /* # number of messages in queue */
msglen_t msg_qbytes; /* Maximum # of bytes in queue */
pid_t msg_lspid; /* PID of last msgsnd(2) */
pid_t msg_lrpid; /* PID of last msgrcv(2) */
};
struct ipc_perm {
key_t __key; /* Key supplied to msgget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions */
unsigned short __seq; /* Sequence number */
};
msgsnd()
#include <sys/types.h>
#inclued <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);
参数:
msqid : 消息队列ID
msgp : 消息结构体指针
msgsz : 消息内容长度
msgflg : 消息队列标志,默认可填0
IPC_NOWAIT : 非阻塞选项
返回值:
成功 : 0
失败 : -1 并设置errno
消息结构体定义模版如下(操作系统并不提该结构体,需要自己按模板实现):
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* 消息数据
前文msgsz最大为该数组长度*/
};
msgrcv()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
ssize_t msgrcv(int msqid,void *msgp,size_t msgsz,long msgtyp,int msgflg);
参数:
msqid : 消息队列id
msgp : 消息结构体指针
msgsz : 可接收 消息的最大长度
msgtyp : 消息类型
> 0 : 读取队列中第一个类型为msgtyp的信息
0 : 读取队列中第一个信息
< 0 : 读取队列中第一个类型最小且<=msgtyp的信息
msgflg : 消息队列标志,默认可填0
IPC_NOWAIT
返回值:
成功 : 返回实际读取消息内容的字节数
失败 : -1,并设置 errno
应用示例
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdio.h>
typedef struct msgbuf
{
long mtype;
char mtext[32];
}msgbuf_t;
int main()
{
//使用路径名"."与序列号100生成键值
key_t key = ftok(".",100);
//获取键值为key,权限为0644的消息队列id,不存在则自动创建该消息队列
int msqid = msgget(key,IPC_CREAT | 0644);
//向id为msqid的消息队列发送消息类型为100,消息内容为hello world的消息
msgbuf_t send_buffer;
send_buffer.mtype = 100;
strcpy(send_buffer.mtext,"hello world");
msgsnd(msqid,&send_buffer,strlen(send_buffer.mtext) + 1,0);
//从id为msqid的消息队列读取一条消息类型为100的消息,且最大可接收消息长度为32
msgbuf_t recv_buffer;
msgrcv(msqid,&recv_buffer,32,100,0);
//打印消息 ==> hello world
printf("%s\n",recv_buffer.mtext);
//删除id为msqid的消息队列
msgctl(msqid,IPC_RMID,NULL);
return 0;
}
sys/shm.h 共享内存
shmget()
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key,size_t size,int shmflg);
功能:
创建一个共享内存,并返回ID
参数:
key : 由ftok()函数返回
size : 共享内存的大小(字节),只获取时可填0
shmflg : 共享内存的标志
0 : 获取共享内存,不存在则报错
IPC_CREAT : 创建共享内存
IPC_EXCL : 和IPC_CREAT一起使用,若共享内存存在,则报错,并设置errno为EEXIST
文件权限标志 : 如0644
返回值:
成功 : 返回共享内存id
失败 : 返回-1 并设置errno
shmctl()
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
功能:
共享内存控制函数,功能由具体的功能命令字决定
参数:
shmid : 共享内存 id
cmd : 控制命令字
IPC_STAT: 获取共享内存属性
IPC_SET : 设置共享内存属性
IPC_RMID : 删除共享内存属性 , 用此命名时,第三个参数为 NULL
buf : 共享内存属性结构体指针
返回值
成功 : 返回 0 ,特殊命令字除外
失败 : 返回 -1
共享内存属性结构体定义如下:
The buf argument is a pointer to a shmid_ds structure, defined in <sys/shm.h> as follows:
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; /* Creation time/time of last
modification via shmctl() */
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 */
...
};
struct ipc_perm {
key_t __key; /* Key supplied to shmget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions + SHM_DEST and
SHM_LOCKED flags */
unsigned short __seq; /* Sequence number */
};
shmat()
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid,const void *shmaddr,int shmflg);
功能:
将进程地址空间映射到共享内存上
参数:
shmid : 共享内存 id
shmaddr : 指定映射到的进程地址空间的起始地址,指定为 NULL 时,由系统选择映射的地址
shmflg : 共享内存标志,默认可设置为 0
SHM_RDONLY : 只读权限
返回值:
成功 : 返回映射到进程地址空间的起始地址
失败 : (void * ) -1,并设置 errno
shmdt()
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
功能:
解除进程地址空间与共享内存的映射
参数:
shmaddr : 映射地址空间的起始地址
返回值:
成功 : 返回 0
失败 : 返回 -1,并设置 errno
应用示例
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
int main()
{
//使用路径名"."与序列号100生成键值
key_t key = ftok(".",100);
//获取键值为key,大小256字节,权限为0644的共享内存id,不存在则自动创建该共享内存
int shmid = shmget(key,256,IPC_CREAT | 0644);
//映射id为shmid的共享内存,自动选取合适内存区域,返回首地址到shmaddr
void *shmaddr = shmat(shmid,NULL,0);
/*操作共享内存
...... */
//解除shmaddr所指的内存映射
shmdt(shmaddr);
//删除id为shmid的共享内存
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
sys/sem.h 信号量
semget()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key,int nsems,int semflag);
功能:
创建一个信号量集合
参数:
key : 由ftok()函数生成
nsems : 信号量的数量
semflg : 信号量集合的标志
IPC_CREAT : 创建标志
IPC_EXCL : 与 IPC_CREAT 标志一起使用,如果信号量集合存在就报错
文件权限标志 : 如0644
返回值:
成功 : 返回信号量集合的id
失败 : -1 并设置errno
semctl()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid,int semnum,int cmd,...);
功能:
信号集合控制函数,根据cmd决定当前函数的功能
参数:
semid : 信号量集合的id
semnum : 信号量的编号, 信号量编号从0开始
cmd : 命令控制字
SETVAL : 设置信号量的值
GETVAL : 获取信号量的值
SETALL : 设置所有信号量的值(将忽略semnum)
GETALL : 获取所有信号量的值(将忽略semnum)
IPC_RMID : 删除信号量集合(将忽略semnum)
...
... : 后面是可变参数,根据不同命令有不同参数
返回值
成功 : 根据不同的命令有不同的返回值,可以查看帮助文档关于 RETURN 的说明
GETNCNT the value of semncnt
GETPID the value of sempid
GETVAL the value of semval
GETALL 返回所有信号量的值到第四个参数arg.array中
GETZCNT the value of semzcnt.
All other cmd values return 0 on success.
失败 : 返回 -1,并设置 errno
第四个参数为union semun 共用体,具体定义模版如下(有些系统库中不提供,需要自己按模版定义):
union semun {
int val; /* 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) */
};
semop()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid,struct sembuf *sops,size_t nsops);
功能:
信号量操作函数,用于占用信号量、释放信号量、设置信号量等待
参数:
semid : 信号量集合id
sops : 信号量操作结构体指针,见struct sembuf定义
nsops : 操作信号量的数量
返回值:
成功 : 0
失败 : -1 并设置errno
struct sembuf具体定义如下:
/* semop system calls takes an array of these. */
struct sembuf {
unsigned short sem_num; /* semaphore index in array 信号量编号,从0 开始*/
short sem_op; /* 信号量操作(以下假设semval初始值为正数)
-n : 占用资源 (semval -= n 若semval<n则阻塞直到占用成功)
+n : 释放资源 (semval += n)
0 : 等待资源 (若semval!=0则阻塞直到semval==0) */
short sem_flg; /* 信号量操作标志
默认可设置为0
IPC_NOWAIT : 非阻塞,在信号量的值为0时,会立即返回
SEM_UNDO : 在进程终止时,会自动释放信号量 */
};
应用示例
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
union semun{
int val;
};
int main()
{
//使用路径名"."与序列号100生成键值
key_t key = ftok(".",100);
//获取键值为key,信号量数量为1,权限为0644的信号量集合id,不存在则自动创建该信号量集合
int semid = semget(key,1,IPC_CREAT | 0644);
//初始化id为semid中的信号量0值为1
union semun sem_init;
sem_init.val = 1;
semctl(semid,0,SETVAL,sem_init);
//抢占id为semid的信号量集合中的信号量0
struct sembuf sops[1];
sops[0].sem_num = 0;
sops[0].sem_op = -1;
sops[0].sem_flg = 0;
semop(semid,sops,1);
/*操作共享资源
.....*/
//释放id为semid的信号量集合中的信号量0
sops[0].sem_op = 1;
semop(semid,sops,1);
//删除id为semid的信号量集合
semctl(semid,0,IPC_RMID);
return 0;
}