IPC(进程间通信)相关常用函数

本文介绍了Linux系统中sys/ipc.h、sys/msg.h、sys/shm.h和sys/sem.h下的关键函数,包括ftok用于生成IPC标识、msgget、msgctl、msgsnd和msgrcv用于消息队列操作,以及shmget、shmat、shmdt用于共享内存管理,以及semget、semctl和semop用于信号量操作。文章提供了详细的应用示例代码。
摘要由CSDN通过智能技术生成

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值