日期:2014-05-16  浏览次数:20710 次

linux 进程间通讯--信号量

PV的定义 P就是请求资源,V就是释放资源

P(sv)    如果sv大于0,减小sv。如果sv为0,挂起这个进程的执行。
V(sv)    如果有进程被挂起等待sv,使其恢复执行。如果没有进行被挂起等待sv,增加sv。

P表示通过的意思V表示释放的意思

System V机制

一.头文件

#include <sys/sem.h>

二.结构体

struct sembuf {
unsigned short   sem_num; /* semaphore index in array */	//处理的信号量个数
short sem_op; /* semaphore operation */	//要执行的操作类型
short sem_flg; /* operation flags */		//操作标识
};
union semun {
    int val;
    struct semid_ds *buf;
    unsigned short  *array;
} arg;

三.API函数

1.获取key_t值

key_t ftok(const char *path, int id);

2.获取设置信号量

int semget(key_t key, int nsems, int semflg);

参数:信号量集键值,信号量格式,信号量标志

返回值:成功返回semid,,错误返回-1,

错误号errno:

    EACCES 权限过低

    EEXIST:id存在,但((semflg &IPC_CREAT) &&(semflg &IPC_EXCL))=0

    EINVAL:nsems参数不对

    ENOENT:id不存在且semflg &IPC_CREAT=0

    ENOSPC:信号量数超过系统限制

当key为IPC_PRIVATE或者当不存在key指定的id时且semflg &IPC_CREAT=0 会创建信号量

 

3.信号量控制

int semctl(int semid, int semnum, int cmd, ...);

参数:信号量集键值,信号量遍号,命令,可选参数(union semun)

返回值:成功返回整数,是吧返回-1

命令:

GETVAL:返回信号量集中的一个单个的信号量的值

SETVAL:设置信号量集中的一个单独的信号量的值

GETPID:返回最后一个执行semop操作的进程的PID

GETNCNT:用于读取信号量集中的所有信号量的值

GETZCNT:返回这在等待完全空闲的资源的进程数目

GETALL:用于读取信号量集中的所有信号量的值

SETVAL:设置信号量集中的一个单独的信号量的值

IPC_STAT:读取一个信号量集的数据结构semid_ds,并将其存储在semun中的buf参数中

IPC_SET:设置信号量集的数据结构semid_ds中的元素ipc_perm,其值取自semun中的buf参数

IPC_RMID:将信号量集从内存中删除

4.信号量操作

int semop(int semid, struct sembuf *sops, size_t nsops); 

参数:信号量集键值,sembuf结构体,操作标志

返回值:成功返回0,失败返回-1

sop->sem_ops的说明:

值为正数,该值会加到现有的信号内含值中。通常用于释放所控资源的使用权;

值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于sem_op的绝对值。通常用于获取资源的使用权;

值为0,则操作将暂时阻塞,直到信号的值变为0

四.例子

 1.

#include <sys/types.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
#include <fcntl.h>
#include <limits.h>
int main(int argc,char **argv)
{
	key_t semkey;
	int semid, pfd, fv;
	struct sembuf sbuf;
	char *lgn;
	char filename[PATH_MAX+1];
	struct stat outstat;
	struct passwd *pw;

	/* Get unique key for semaphore. */
	if ((semkey = ftok("/tmp", 'b')) == (key_t) -1) {
		perror("IPC error: ftok"); exit(1);
	}

	/* Get semaphore ID associated with this key. */
	if ((semid = semget(semkey, 0, 0)) == -1) {
		/* Semaphore does not exist - Create. */
		if ((semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) != -1)
		{
		    /* Initialize the semaphore. */
		    sbuf.sem_num = 0;
		    sbuf.sem_op = 2;  /* This is the number of runswithout queuing. */
		    sbuf.sem_flg = 0;
		    if (semop(semid, &sbuf, 1) == -1) {
		        perror("IPC error: semop"); exit(1);
		    }
		}
		else if (errno == EEXIST) {
		    if ((semid = semget(semkey, 0, 0)) == -1) {
		        perror("IPC error 1: semget"); exit(1);
		    }
		}
		else {
		    perror("IPC error 2: semget"); exit(1);
		}
	}
}

2.网上找到的例子

#include <sys/types