Linux系统编程.NO14——IPC与IPC实现

11.进程间通信

11.1.IPC概念

IPC是指进程间通信,这里主要是指system V IPC。主要包括消息队列,共享内存和信号量三种方式。这三种IPC的使用方法类似,都属于系统的IPC资源。
IPC有一些相通的属性,IPC只能在本机通信中使用,不能跨网络,IPC的生存期与内核相同,也就是除非用户删除它,否则将永远存在。每个IPC资源都有一个关键字key(就像该资源的文件名一样,是一个长整型的数),同时资源被创建的时候会获得一个整数标识ID(就像文件描述符,任何进程都可以通过这个ID来访问该资源)。
每个IPC资源都有一个结构体来记录该资源的属性(好比文件都有一个inode结构体记录属性),其结构体有一个成员是ipc_perm表明了该资源的访问权限(就像inode中的st_mode)。
Linux提供了ipcs查看和ipcrm删除pc资源的命令。
对于ipc资源只有读写权限,没有执行权限。

11.2.信号量

信号量就是一个计数器,多个进程访问共享对象的时候使用信号量实现同步操作。
1.int semget(key_t key,int nsems,int semflg)
功能是创建一个信号量,key表示信号量的键值,需要手动确定,nsems是指信号量的个数。
semflg是创建标志,同open()函数的权限位,填IPC_CREAT表示创建或打开一个新的信号量,或者填IPC_CREAT|0660(即标明权限),如果填IPC_CREAT|IPC_EXCL,则创建一个新的信号量,若已经存在则会报错。成功创建返回信号量集ID号,失败返回-1.
本函数用于创建一个信号量集合,访问集合内指定的信号量使用ID+序号的方式,所以返回的ID是属于这个集合内所有信号量的,就像是数组名一样。
头文件是
2.int semctl(int semid,int semnum,int cmd,…)
信号量的控制函数,semid是信号量的ID,semnum是信号量集中信号量的序号,cmd则是具体要进行的操作,可选填的参数有:
IPC_STAT获取信号量集的内核信息
IPC_SET设置信号量集的内核信息
IPC_RMID立即删除该信号量集合
GETVAL返回成员semnum的semval值,这个是指信号量的值,信号量实际上就是一个计数器,该值就是当前计数器的值
SETVAL设置成员semnum的semval值
GETPID返回成员semnum的sempid,即前一个对此信号量进行操作的进程号
GETNCNT返回成员semnum的semncnt值,即等待信号量的值增加的进程的个数
GETZCNT返回成员semnum的semzcnt值,即等待信号量的值变为0的进程的个数
GETALL取消该集合中所有信号量的值,并将它们存放在由arg.array指向的数组中
SETALL按照arg.array指向的数组中的值设置该集合中所有信号量的值
函数失败返回-1,成功根据cmd返回不同的结果
头文件是
当cmd是SETVAL,IPC_STAT,IPC_SET,GETAll,SETALL时,实际上是在操作一个联合体中的成员:
union semun{
int val; //信号量的值,计数器的值
struct semid_ds *buf//获取或设置内核新的缓冲
unsigned short *array//cmd为GETALL的指针
sruct seminfo *__buf//cmd为IPC_INOF时}
如果cmd是查询类的参数,如GETVAL,第四个参数必须是一个union semun类型的对象(事先定义一个这个类型的变量填在这里即可),如果cmd是设置类的参数,如SETVAL,则第四个参数表示具体设置的值,如(semid,0,SETVAL,1)将0号信号量设置为1.
3.int semop(int semid,struct sembuf *sops,unsigned nsops)
函数功能是改变信号量的值,具体如何改变根据一个结构体来设置:
struct sembuf{
short sem_num;//信号量序号,单个信号量置0
short sem_op;//在信号量上执行的操作(P/V)
short sem_flg;//通常为SEM_UNDO,使操作系统跟踪信号,作用是在进程如果没有释放该信号量就终止了,操作系统就主动释放信号量。}
该结构体使用前必须要先初始化,将sem_op置+1,则每次使用该结构体就会执行一次V操作,将sem_op置-1,则每次使用该结构体就会执行一次P操作
semid是semget函数返回的ID,sops 是一个sembuf类型的变量,前提是已经初始化完成,只要已经初始化完成,就决定了该函数是进行P操作还是V操作。nsops则指明执行本操作的次数,一般填1,表示进行一次P操作或进行一次V操作。
函数成功执行返回0,失败返回-1
头文件是

11.3.共享内存

共享内存是最快的IPC方式,使得多个进程可以访问一段指定的内存区。
1.int shmget(key_t key,size_t size,int shmflg)
函数用于创建一块共享内存空间,key是自定义的关键字,size指定以字节为单位的内存区大小,size应该要大于0,shmflg是创建标志,和semget函数的第三个参数完全一样。成功返回共享内存ID,失败返回-1。
头文件是
2.void *shmat(int shmid,const void *shmaddr,int shmflg)
函数功能是共享内存地址映射,shmid是shmget函数返回的ID号,shmaddr是映射地址,也就是指定共享内存映射到当前进程中的地址,一般填NULL,让系统自动选择,shmflg是映射方式,一般填0,以读写方式连接地址,可以填SHM_RDONLY,表示以只读方式进行映射。
函数返回映射的本进程的地址,失败返回-1.
头文件是
3.int shmdt(const void *shmaddr)
解除地址映射,参数是shmat函数的返回值,即映射的本进程的地址。成功返回0,失败返回-1.
头文件是
4.int shmctl(int shmid,int cmd,struct shmid_ds *buf)
功能是控制共享内存,shmid是由shmget函数返回的ID,cmd是需要执行的命令,buf是一个执行shmid_ds结构体的指针,该结构体指明了访问权限,没有要求时可以填NULL。
struct shmid_ds{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;}
cmd的可选项有:IPC_STAT获取共享内存的信息,存储在这个结构体中,IPC_SET设置更新内存的信息,即更新这个结构体的成员,IPC_RMID删除本共享内存。返回0/-1对错码。
头文件是

11.4.消息队列

系统提供消息队列的IPC,进程将消息发送到消息队列,直到另一个进程将其取走。消息由固定长度的消息首部和可变长度的消息正文组成。
1.int msgget(key_t key,int msgflg)
函数功能是创建或打开一个消息队列,key是自定义的关键字,msgflg可以设置为IPC_CREAT或IPC_CREAT|IPC_EXCL此时该函数会创建一个消息队列,如果要打开一个消息队列,msgflg就是指定为访问消息队列的权限。
函数返回消息队列ID,失败返回-1
头文件是
2.int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg)
消息队列的每个消息信息包含在一个结构体中:
struct msgbuf{
long mtype;//消息的类型
char mtex[1];//消息正文}
功能是发布一个消息,msqid是消息队列的ID,msgp指具体要发送的消息的首地址,就是一个指向msgbuf结构的指针,msgsz值发送消息的长度,也就是指定mtex的最大值
msgflg指发送方式,可以为0,若为IPC_NOWAIT如果消息队列满了,消息就不会写入队列,控制权返回调用函数的线程,如果不指定这个参数,线程将被阻塞到可以写入消息为止。成功返回消息队列ID,失败返回-1。
头文件是
3.ssize_t msgrcv(int msqid,void *msgp,size_t msgsz,long msgtyp,int msgflg)
msqid是消息队列的ID,msgsz指定mtext成员最大字节,msgtyp指定要接受的消息类型,msgp和msgsnd函数的msgp一样。
msgtyp置0,接收队列中第一个消息,大于0接收队列中第一个类型为msgtyp的消息,小于0接收消息队列中第一个类型值不小于msgtyp的绝对值且类型值最小的消息。
msgfly置0表示阻塞调用,直到接收到一条满足要求的消息才返回,置IPC_NOWAIT表示如果队列中没有要求的信息则马上返回,置MSG_NOERROR表示如果返回的字节比msgsz的字节多,则消息就会截断到msgsz字节。成功返回消息正文字节数,错误返回-1.
头文件是
4.int msgctl(int msqid,int cmd,struct msqid_ds *buf)
消息队列的控制函数,msgid是消息队列的ID,cmd是控制命令。buf是一个描述消息队列的msqid_ds结构类型的变量
控制命令可选有:
IPC_STAT获取msqid消息队列在内核中的信息,存储在buf指向的msqid_ds对象中
IPC_SET设置新的消息队列在内核中的信息,新的信息由buf指向的msqid_ds给出。
IPC_RMID删除本消息队列。返回值是0/-1对错码。
头文件是

11.5.生成key

系统提供了一个生成key值的函数。
key_t ftok(const char *pathname,int id)
pathname是一个任意的文件名,id是一个任意的数值,只要保证id的低八位不是0即可,返回值即是一个生成的key值。
key值可以填IPC_PRIVATE表示要创建一个新的资源而不是打开一个已有的资源。
头文件是

你可能感兴趣的:(Linux系统编程,信号量,共享内存,IPC,KEY,Linux系统编程)