System V 信号灯

24 篇文章 0 订阅
1.semget函数创建一个信号灯集或访问一个已存在的信号灯集
#include <sys/sem.h>
int semget(key_t key, int nsems, int oflags);返回一个信号灯的标识符。
nsems指定集合中的信号灯数,如果只是打开一个已存在的集合,则该参数指定为0.创建完一个信号灯集,就不能改变其中的信号灯数。
oflags值是SEM_R和SEM_A常值的组合。也可以与IPC_CREAT或IPC_CREAT|IPC_EXCL组合。

semctl函数对一个信号灯执行各种控制操作。
int semctl(int semid, int semnum, int cmd, ...);
semid标识待控制其操作的信号灯集,semnum标识该信号灯集中的第semnum个(从0开始)成员,semnum值仅仅用于GETVAL、SETVAL、GETNCNT、GETZCNT和GETPID命令。
System V支持下列cmd值:
    GETVAL,SETVAL,GETPID,GETNCNT,GETZCNT,GETALL,SETALL,IPC_RMID,IPC_SET,IPC_STAT

对于系统中的每个信号灯集,内核维护一个如下的信息结构:
struct semid_ds
{
struct ipc_perm sem_perm;  // operation permission
struct sem *sem_base;      // ptr to array of semaphores in set
unsigned short sem_nsems;  // number of semaphres in set
time_t sem_otime;          // time of last semop()
time_t sem_ctime;          // time of creation or last IPC_SET
};
其中,struct sem结构如下:
struct sem
{
unsigned short semval;     // semaphore value, nonnective
short sempid;              // pid of last seccessful semop(),
                          // SETVAL,SETALL
unsigned short semncnt;    // awaiting semval > current value
unsigned short semzcnt;    // awaiting semval = 0
};


*) GETVAL 把semval的当前值作为函数返回值返回;

*) SETVAL 把semval的值设置为arg.val;
*) GETPID 返回sempid的当前值
*) GETNCNT 把semncnt的当前值返回
*) GETZCNT 把semzcnt的当前值返回
*) GETALL 把指定信号灯集中的每个成员的semval值返回,调用者必须分配足够容纳所指定信号灯集中所有成员的semval值的一个unsigned short整数数组,然后把arg.array设置成指向这个数组。
*) SETALL 设置所指定信号灯集中每个成员的semval值。这些值通过arg.array数组指定。
*) IPC_RMID 把由semid指定的信号灯集从系统中删除。
*) IPC_SET 设置所指定信号灯集的semid_ds结构中的一下三个成员:sem_perm.uid,sem_perm.gid和sem_perm.mode,这些值由来自arg.buf参数指向的结构中的相映成员。
*) IPC_STAT 返回所指定的信号灯集的当前semid_ds结构。调用者必须首先分配一个semid_ds结构,并把arg.buf设置成指向这个结构。

使用semget打开一个信号灯集合后,对其中的一个或多个信号灯的操作就使用semop函数来执行。
int semop(int semid, struct sembuf *opsptr, size_t nops);
semop函数用来对一个或多个信号灯进行操作。

其中struct sembuf结构为:
struct sembuf
{
short sem_num;   // semaphores number
short sem_op;    // semaphores operations
short sem_flg;   // operation flags: 0, IPC_NOWAIT, SEM_UNDO
};

nops参数指出由opsptr指向的sembuf结构数组中元素的数目。

// semcreat.c
#include <sys/types.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <unistd.h>

#define SVSEM_MODE 0644

int main(int argc, char **argv)
{
int c, oflag, semid, nsems;

oflag = SVSEM_MODE | IPC_CREAT;
while((c = getopt(argc, argv, "e")) != -1)
{
switch(c)
{
case 'e':
oflag |= IPC_EXCL;
break;
}
}

if(optind != argc - 2)
{
perror("usage: semcreat [-e] <pathname> <nsems>");
exit(0);
}

nsems = atoi(argv[optind + 1]);
semid = semget(ftok(argv[optind], 0), nsems, oflag);

return 0;
}

// semgetvalues.c
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <stdio.h>

union semun
{
	int val;
	struct semid_ds *buf;
	unsigned short *array;
};

int main(int argc, char **argv)
{
	int semid, nsems, i;
	struct semid_ds seminfo;
	unsigned short *ptr;
	union semun arg;

	if(argc != 2)
	{
		perror("usage: semgetvalues <pathname>");
		exit(0);
	}

	semid = semget(ftok(argv[1], 0), 0, 0);
	arg.buf = &seminfo;
	semctl(semid, 0, IPC_STAT, arg);
	nsems = arg.buf->sem_nsems;

	ptr = calloc(nsems, sizeof(unsigned short));
	arg.array = ptr;

	semctl(semid, 0, GETALL, arg);
	for(i = 0; i < nsems; i++)
		printf("semval[%d] = %d\n", i, ptr[i]);
	return 0;
}

// semops.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <unistd.h>

union semun
{
	int va;
	struct semid_ds *buf;
	unsigned short *array;
};

int main(int argc, char **argv)
{
	int c, i, flag, semid, nops;
	struct sembuf *ptr;

	flag = 0;
	while((c = getopt(argc, argv, "nu")) != -1)
	{
		switch(c)
		{
			case 'n':
				flag |= IPC_NOWAIT;
				break;
			case 'u':
				flag |= SEM_UNDO;
				break;
		}
	}

	if(argc - optind < 2)
	{
		perror("usage: semops [-n] [-u] <pathname> operation ...");
		exit(0);
	}

	semid = semget(ftok(argv[optind], 0), 0, 0);
	optind++;
	nops = argc - optind;

	ptr = calloc(nops, sizeof(struct sembuf));
	for(i = 0; i < nops; i++)
	{
		ptr[i].sem_num = i;
		ptr[i].sem_op = atoi(argv[optind + i]);
		ptr[i].sem_flg = flag;
	}
	semop(semid, ptr, nops);

	return 0;
}

// semid.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
	int semid;

	if(argc != 2)
	{
		perror("usage: semid <pathname>");
		exit(0);
	}

	semid = semget(ftok(argv[1], 0), 0, 0);
	semctl(semid, 0, IPC_RMID);

	exit(0);
}

// semsetvalues.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <sys/sem.h>

union semun
{
	int val;
	struct semid_ds *buf;
	unsigned short *array;
};


int main(int argc, char **argv)
{
	int semid, nsems, i;
	struct semid_ds seminfo;
	unsigned short *ptr;
	union semun arg;

	if(argc < 2)
	{
		perror("usage: semsetvalues <pathname> [values ...]");
		exit(0);
	}
	semid = semget(ftok(argv[1], 0), 0, 0);
	arg.buf = &seminfo;
	semctl(semid, 0, IPC_STAT, arg);
	nsems = arg.buf->sem_nsems;

	if(argc != nsems + 2)
	{
		perror("%d semaphores in set, %d values specified", nsems, argc - 2);
		exit(0);
	}

	ptr = calloc(nsems, sizeof(unsigned short));
	arg.array = ptr;

	for(i = 0; i < nsems; i++)
		ptr[i] = atoi(argv[i + 2]);
	semctl(semid, 0, SETALL, arg);
	return 0;
}

[test@localhost] touch info

[test@localhost] ./semcreat -e info 3

[test@localhost] ./semsetvalues info 1 2 3

[test@localhost]  ./semgetvalues info

semval[0] = 1

semval[1] = 2

semval[2] = 3

[test@localhost] ./semops -u info -1 -2 -3  # 给每个操作指定SEM_UNDO标志

[test@localhost] ./semgetvalues info

semval[0] = 1                                                 # 当semops终止时,所有变动都取消

semval[1] = 2

semval[2] = 3

[test@localhost] ./semops info -1 -2 -3       # 不指定SEM_UNDO标志

[test@localhost] ./semgetvalues info

semval[0] = 0                                                 # 变动未被取消

semval[1] = 0

semval[2] = 0



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值