进程间通信之信号量

    信号量又称为信号灯,它是用来协调不同进程间的数据对象的(进程间数据同步)。本质声,信号量是一个计数器,它用来记录对某个资源的存取状况。一般来说,为了获得共享资源,进程需要执行以下操作:

        1.测试控制该资源的信号量

        2.若此信号量的值为正,则允许进行使用该资源。进程将信号量减1

        3.若此信号量为0,则该资源目前不可用,进程进入睡眠状态,直至信号量值大于0,进程被唤醒,转入步骤1

        4.当进程不再使用一个信号量控制的资源时,信号量值加1。若此时有进程正在睡眠等待此信号量,则唤醒此进程。

示例1.1

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

#define IPC_KEY 0x00001234
int sem_id = -1;
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) */
};
/*
   struct sembuf
   {
	 unsigned short int sem_num;  // semaphore number 
	 short int sem_op;     // semaphore operation 
	 short int sem_flg;        // operation flag 
   };
   */
int sem_p()
{
	struct sembuf buf;
	buf.sem_num = 0;
	buf.sem_op = -1;
	buf.sem_flg = SEM_UNDO;

	semop(sem_id, &buf, 1);
}

int sem_v()
{
	struct sembuf buf;
	buf.sem_num = 0;
	buf.sem_op = 1;
	buf.sem_flg = SEM_UNDO;

	semop(sem_id, &buf, 1);
}


int main(int argc, char *argv[])
{
	union semun arg;
	arg.val = 1;
	sem_id = semget(IPC_KEY, 1, IPC_CREAT|0664); //赋予权限
	if (sem_id < 0){
		printf("semget error!!\n");
		return -1;
	}

	semctl(sem_id, 0, SETVAL, arg);

	while (1){
		sem_p();
		printf("test 1\n");
		sleep(1);
		sem_v();
	}
	semctl(sem_id, 0, IPC_RMID, NULL);
	return 0;
}

示例1.2

    

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

#define IPC_KEY 0x00001234
int sem_id = -1;

int sem_p()
{
	struct sembuf buf;
	buf.sem_num = 0;
	buf.sem_op = -1;                               
	buf.sem_flg = SEM_UNDO;                        

	semop(sem_id, &buf, 1);
}

int sem_v()
{
	struct sembuf buf;
	buf.sem_num = 0;
	buf.sem_op = 1;
	buf.sem_flg = SEM_UNDO;

	semop(sem_id, &buf, 1); 
}


int main(int argc, char *argv[])
{
	sem_id = semget(IPC_KEY, 1, IPC_CREAT);
	if (sem_id < 0){
		printf("semget error!!\n");
		return -1;
	}
	while (1){
		sem_p();
		printf("Test 2\n");
		sleep(3);
		sem_v();
	}
	return 0;
}

    1.使用semget函数创建信号量

    2.使用semctl中的SETVAL对信号量进行初始化

    3.同步前使用semop对信号量进行检测及P操作(减1)

    4.同步完成对信号量进行V操作(加1)

    5.使用semctl中的IPC_RMID删除信号量

Linux下查看信号量:sudo ipcs -s


Linux删除信号量:ipcrm -s semid

猜你喜欢

转载自blog.csdn.net/qq_33408113/article/details/80013554