Linux内核篇之SYSTEM-V
1.消息队列
system-v ipc特点:
- 独立于进程
- 没有文件名和文件描述符
- IPC对象具有Key和ID
消息队列用法:
- 定义一个唯一Key (ftok)
- 构造消息对象(msgget)
- 发送特定类型的消息(msgsnd)
- 接受特定类型的消息(msgrcv)
- 删除消息队列(msgct)
相关函数:
-
ftok
- 功能 :获取一个Key
- 函数原型:ket_t ftok(const char *path,int proj_id)
- 参数:
- path:一个合法路径
- proj_id:一个整数
- 返回值:
- 成功:合法Key
- 失败:-1
- 参数:
-
msgget
- 功能:获取消息队列ID
- 函数原型:int msgget(key_t key,int msgflg)
- 参数:
- key:消息队列key
- msgflg:
- IPC_CREAT:如果消息队列不存在则创建一个
- mode:访问权限
- 权限只有读和写,执行权限是无效的,例如 0777 跟 0666 是等价的。
当 key 被指定为 IPC_PRIVATE 时,系统会自动产生一个未用的 key 来对应一个新的消
息队列对象,这个消息队列一般用于进程内部间的通信。
- 返回值:
- 成功:返回消息队列ID
- 失败:-1
-
msgsnd
-
功能:发送消息到消息队列
-
函数原型:int msgsnd(int msqid,const void*msgp,size_t msgsz,int msgflg)
-
参数:
-
msqid:消息队列ID
-
msgp:消息缓存区
-
struct msgbuf
{
long mtype;//消息标识
char mtext[1];//消息内容
}
-
-
msgsz:消息正文的字节数
-
msgflg:
- ipc_nowait:非阻塞发送
- 0:阻塞发送
-
返回值:
- 成功:0
- 失败:-1
-
-
-
msgrcv:
-
功能:从消息对接读取消息
-
返回值:
- 成功:0
- 失败:-1
-
函数原型:ssize_t msgrcv(int msqid,void *msgp,size_t msgsz,long msgtyp,int msgflg);
-
参数:
-
msqid:消息队列lD
-
msgp:消息缓存区
-
nsgsz:消息正文的字节数
-
msgtyp:要接受消息的标识
-
msgflg:
- IPC_NOWAIT:非阻塞读取
- MSG NOERROR:载断消息
- 0:阻塞读取
-
-
-
msgctl:
- 功能:设置获取消息队列的相关属性
- 函数原型:int msgctl(int msgqid,int cmd,struct maqid_ds *buf)
- 参数:
- msgqid:消息队列id
- cmd:
- IPC_STAT:获取消息队列的属性
- IPC_SET:设置消息队列的属性
- IPC_RMID:删除消息队列
- buf:相关结构体缓冲区
2.信号量
本质:计数器
作用:保护共享资源
- 互斥 :在一个时刻只有一个进程可以访问
- 同步 :在互斥访问的基础上加上顺序
1.临界资源
临界资源是一次仅允许一个进程使用的共享资源。各进程采取互斥的方式,实现共享的资源称作临界资源。属于临界资源的硬件有,打印机,磁带机等;软件有消息队列,变量,数组,缓冲区等。诸进程间采取互斥方式,实现对这种资源的共享。
2.临界区:
每个进程中访问临界资源的那段代码称为临界区(criticalsection),每次只允许一个进程进入临界区,进入后,不允许其他进程进入。不论是硬件临界资源还是软件临界资源,多个进程必须互斥的对它进行访问。多个进程涉及到同一个临界资源的的临界区称为相关临界区。使用临界区时,一般不允许其运行时间过长,只要运行在临界区的线程还没有离开,其他所有进入此临界区的线程都会被挂起而进入等待状态,并在一定程度上影响程序的运行性能。
信号量工作原理:
- 由于信号量只能进行两种操作:等待和发送信号,即 P 操作和 V 操作,锁行为就是 P 操作,解锁就是 V 操作,可以直接理解为 P 操作是申请资源, V 操作是释放资源。 PV 操作是计算机操作
- 系统需要提供的基本功能之一,它们的行为是这样的:
- P 操作:如果有可用的资源(信号量值大于 0),则占用一个资源(给信号量值减去一,进
入临界区代码) ; 如果没有可用的资源(信号量值等于 0),则阻塞,直到系统将资源分配
给该进程(进入等待队列,一直等到资源轮到该进程)。这就像你要把车开进停车场之前,
先要向保安申请一张停车卡一样, P 操作就是申请资源,如果申请成功,资源数(空闲的停
车位)将会减少一个,如果申请失败,要不在门口等,要不就走人。 - V 操作:如果在该信号量的等待队列中有进程在等待资源,则唤醒一个阻塞的进程。如果
没有进程等待它,则释放一个资源(给信号量值加一),就跟你从停车场出去的时候一样,
空闲的停车位就会增加一个
- P 操作:如果有可用的资源(信号量值大于 0),则占用一个资源(给信号量值减去一,进
信号量的用法:
- 定义一个唯一key(ftok)
- 构造一个信号量(semget)
- 初始化信号量(semctl SETVA)
- 信号量进行P/V操作(semop)
- 删除信号集(semctl RMID)
semget函数:
- 功能:获取信号量 ID
- 函数原型:int semget(key_t key ,int nsems, int semflg)
- 参数:
- key: 信号量键值
- nsems:信号量数值
- semflg:
- IPC_CREAT:信号量不存则创建
- mode:权限
- 返回值:
- 成功:信号量ID
- 失败:-1
semctl函数:
-
功能:获取或设置信号量的相关属性操作
-
函数原型:int semctl(int semid,int semnum,int cmd,union semun arg)
-
参数:
-
semid:信号量的ID
-
semnum:信号量的编号
-
cmd:
- IPC_STAT:获取信号量的属性信息
- IPC_SET:设置信号量的属性
- IPC_RMID:删除信号量
- IPC_SETVAL:设置信号量的值
-
arg:
union semun { int val; struct semid_ds *buf; }
- 返回值:
- 成功:由CMD类型决定
- 失败:-1
- 返回值:
-
semop函数:
-
功能:对信号量进行加减操作
-
函数原型:int semop(int semid,struct sembuf *sops,size_t nsops)
-
参数:
-
semid: 信号量ID
-
sops:信号量操作结构体数组
struct sembuf { short sem_num;//信号量编号 short sem_op;//信号量P/V操作 short sem_flg;//信号量行为 SEM_UNDO }
-
nsops:信号量数量
-
返回值:
-
成功:0
-
失败:-1
-
-