#include <unistd.h> #include <stdlib.h> #include <stdio.h>

#include <sys/sem.h> //包含信号量定义的头文件

//联合类型semun定义 union semun { int val; struct semid_ds *buf; unsigned short *array; };

//函数声明 //函数:设置信号量的值 static int set_semvalue(void); //函数:删除信号量 static void del_semvalue(void); //函数:信号量P操作 static int semaphore_p(void); //函数:信号量V操作 static int semaphore_v(void);

static int sem_id; //信号量ID

int main(int argc, char *argv[]) { int i; int pause_time; char op_char = 'O';

srand((unsigned int)getpid());

//创建一个新的信号量或者是取得一个已有信号量的键
sem_id = semget((key_t)1234, 1, 0666 | IPC_CREAT);

//如果参数数量大于1,则这个程序负责创建信号和删除信号量
if (argc > 1) {
	if (!set_semvalue()) {
		fprintf(stderr, "failed to initialize semaphore\n");
		exit(EXIT_FAILURE);
	}

	op_char = 'X'; //对进程进行标记
	sleep(5);
}

//循环:访问临界区
for (i = 0; i < 10; ++i) {
	//P操作,尝试进入缓冲区
	if (!semaphore_p())
		exit(EXIT_FAILURE);
	printf('%c', op_char);
	fflush(stdout); //刷新标准输出缓冲区,把输出缓冲区里的东西打印到标准输出设备上

	pause_time = rand() % 3;
	sleep(pause_time);

	printf('%c', op_char);
	fflush(stdout);

	//V操作,尝试离开缓冲区
	if (!semaphore_v())
		exit(EXIT_FAILURE);
	pause_time = rand() % 2;
	sleep(pause_time);
}

printf("\n %d - finished \n", getpid());

if (argc > 1) {
	sleep(10);
	del_semvalue(); //删除信号量
}

}

//函数:设置信号量的值 static int set_semvalue(void) { union semun sem_union; sem_union.val = 1;

if (semctl(sem_id, 0, SETVAL, sem_union))
	return 0;

return 1;

}

//函数:删除信号量 static void del_semvalue(void) { union semun sem_union;

if (semctl(sem_id, 0, IPC_RMID, sem_union))
	fprintf(stderr, "Failed to delete semaphore\n");

}

//函数:信号量P操作:对信号量进行减一操作 static int semaphore_p(void) { struct sembuf sem_b;

sem_b.sem_num = 0; //信号量编号
sem_b.sem_op = -1; //P操作	
sem_b.sem_flg = SEM_UNDO;

if (semop(sem_id, &sem_b, 1) == -1) {
	fprintf(stderr, "semaphore_p failed\n");
	return 0;
}

return 1;

}

//函数:信号量V操作:对信号量进行加一操作 static int semaphore_v(void) { struct sembuf sem_b;

sem_b.sem_num = 0; //信号量编号
sem_b.sem_op = 1; //V操作	
sem_b.sem_flg = SEM_UNDO;

if (semop(sem_id, &sem_b, 1) == -1) {
	fprintf(stderr, "semaphore_v failed\n");
	return 0;
}
return 1;

}

//解释程序内容:这是一个使用信号量实现进程同步的程序。程序中创建了一个信号量,多个进程可以使用该信号量来控制对临界区的访问。

//在程序中,如果命令行参数数量大于1,则表示该进程是创建信号量的进程,否则表示该进程是使用信号量的进程。创建信号量的进程会初始化信号量的值为1,并在5秒后退出程序。使用信号量的进程会循环10次,每次尝试进入临界区并输出一个字符,然后随机等待一段时间再离开临界区,再随机等待一段时间后再次尝试进入临界区。进入临界区时,使用信号量的进程会执行P操作,尝试减少信号量的值,如果信号量的值为0,则阻塞等待直到信号量的值大于0。离开临界区时,使用信号量的进程会执行V操作,尝试增加信号量的值。

//程序中的set_semvalue函数用于初始化信号量的值,del_semvalue函数用于删除信号量,semaphore_p函数用于执行P操作,semaphore_v函数用于执行V操作。

Linux 信号量同步:多进程访问临界区示例

原文地址: https://www.cveoy.top/t/topic/kUMe 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录