分享

Linux的进程通讯之信号量

 wythe 2023-05-25 发布于广东

在 Linux 中,进程间通信的另一个机制是信号量。信号量是一种计数器,用于实现并发机制以及防止对共享内存的同时访问。当一个进程访问共享数据时,它可以使用信号量来阻止其他进程访问该数据,直到共享数据被释放。

信号量的创建和操作使用的是semget、semop和semctl等系统调用。

使用示例:

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

#define KEY 0x2023
union semun
{
    int val;                /* SETVAL 用,设置信号量的初始值 */
    struct semid_ds *buf;   /* IPC_STAT 和 IPC_SET 用,访问信号量的参数 */
    unsigned short *array;  /* GETALL 和 SETALL 用,获取或设置信号量的数组值 */
};

void P(int semid)
{
	struct sembuf buf;
	buf.sem_num = 0;
	buf.sem_op = -1;  //P : -1 V: 1
	buf.sem_flg = SEM_UNDO;
	
	if(semop(semid,&buf , 1) == -1)
	{
		perror("sem P error");
	}
}



void V(int semid)
{
	struct sembuf buf;
	buf.sem_num = 0;
	buf.sem_op = 1;  //P : -1 V: 1
	buf.sem_flg = SEM_UNDO;
	
	if(semop(semid,&buf , 1) == -1)
	{
		perror("sem V error");
	}
}
void sem_destory(int semid) {         
	if(semctl(semid,0,IPC_RMID)==-1)                 
		perror("destory sem error");
}

int main(int argc,char **argv)
{
    int semid = 0 ;
	int n = 0;
	int creat_ps = 1;
	int cnt = 0;
	//union semun *p = NULL;
	//union semun a;
	
	semid = semget(KEY, 1 , IPC_CREAT | IPC_EXCL | 0666 );
	
	if(semid == -1 )
	{
		semid = semget(KEY, 1 , 0666 );
		if(semid == -1)
		{
			perror("sem get error");
			goto exits;
		}
		else
		{
			/*p = (union semun *)malloc(sizeof(union semun));
			if(p == NULL)
			{
				goto exits;
			}
			p->val = 1;*/
			union semun a;
			a.val = 1;
			
			//if(semctl(semid, 0 , SETVAL , *p ) ==  -1)
			if(semctl(semid, 0 , SETVAL , a ) ==  -1)
			{
				perror("sem init error");
				goto exits;
			}
			creat_ps = 0;
		}
	}
	printf("start run %d\n", creat_ps);
	while(1)
	{
		
		P(semid);
		fflush(stdout);
		if(creat_ps)
		{
			printf("AAAAAAAAAAAAAAAAAAA\n");
			printf("        11         \n");
			printf("        11         \n");
			printf("AAAAAAAAAAAAAAAAAAA\n");
			printf("\n\n");
		}
		else
		{
			printf("BBBBBBBBBBBBBBBBBBB\n");
			printf("        22         \n");
			printf("BBBBBBBBBBBBBBBBBBB\n");
			printf("\n\n");
		}
		V(semid);
		n = rand()%3;
		sleep(n);
		cnt++;
		if(cnt > 10)
			break;
	}
exits:	
	if(creat_ps)
		sem_destory(semid);
	
	/*if(p != NULL)
	{
		free(p);
	}*/


    return 0;
}

执行结果:

开启两个不同进程,进程A

wythe@XXXXX:~/linux-sys$ ./sem
start run 1
AAAAAAAAAAAAAAAAAAA
        11         
        11         
AAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAA
        11         
        11         
AAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAA
        11         
        11         
AAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAA
        11         
        11         
AAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAA
        11         
        11         
AAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAA
        11         
        11         
AAAAAAAAAAAAAAAAAAA

进程B

wythe@xxxxx:~/linux-sys$ ./sem
start run 0
BBBBBBBBBBBBBBBBBBB
        22         
BBBBBBBBBBBBBBBBBBB


BBBBBBBBBBBBBBBBBBB
        22         
BBBBBBBBBBBBBBBBBBB


BBBBBBBBBBBBBBBBBBB
        22         
BBBBBBBBBBBBBBBBBBB


BBBBBBBBBBBBBBBBBBB
        22         
BBBBBBBBBBBBBBBBBBB

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多