-- TOC --
进程间的同步,可以使用命名信号量(named semaphore)。
$ man 7 sem_overview
named semaphore在创建后,位于/dev/shm
路径下。
fork后的子进程,继承了semaphore,但是不会继承对semaphore的操作。
下面是测试代码,多进程同时读写一个硬盘文件:
$ cat test_sem.c
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/wait.h>
#define _PEXIT \
do {\
char ebuf[64] = {0};\
sprintf(ebuf, "%s: %d", __FILE__, __LINE__);\
perror(ebuf);\
exit(errno);\
}while(0)
void increment1(sem_t *sem, char *file_name) {
sem_wait(sem);
int a;
FILE *fp = fopen(file_name, "r");
fscanf(fp, "%d", &a);
fclose(fp);
fp = fopen(file_name, "w");
fprintf(fp, "%d", a+1);
fclose(fp);
sem_post(sem);
}
int main(int argc, char **argv) {
/* child process number */
int pnum;
if (argc == 2)
pnum = atoi(argv[1]);
else
pnum = 4; /* default child process number */
/* create a file which contain a number zero */
char *file_name = "number.txt";
FILE *fp = fopen(file_name, "w");
if (fp == NULL)
_PEXIT;
fprintf(fp, "%d", 0);
fclose(fp);
/* create a semaphore with value 1 */
char *sem_name = "/sem_test";
sem_t *sem;
sem = sem_open(sem_name, O_CREAT|O_RDWR, 0666, 1);
if (sem == SEM_FAILED)
_PEXIT;
/* fork child */
int cnum = pnum;
pid_t cpid;
while (cnum--) {
if ((cpid=fork()) == 0) {
/* add 2 */
increment1(sem, file_name);
increment1(sem, file_name);
exit(0);
} else if (cpid == -1)
_PEXIT;
}
/* wait all */
int wnum = pnum;
while (wnum--)
wait(NULL);
/* read out final number */
int a;
fp = fopen(file_name, "r");
fscanf(fp, "%d", &a);
fclose(fp);
printf("%d\n", a);
/* close and remove semaphore */
sem_close(sem);
sem_unlink(sem_name);
/* delete file */
unlink(file_name);
return 0;
}
文件中只有一个数字,进程每次获取到semaphore之后,对此数字进行+1操作。默认开启4个子进程,每个子进程执行两次+1。
运行效果如下:
$ gcc -Wall -Wextra test_sem.c -o test_sem
$ ./test_sem
8
$ ./test_sem 8
16
$ ./test_sem 80
160
$ ./test_sem 800
1600
代码测试结果符合预期,多个进程确实同步了。
进程间也可以使用匿名信号量,需要将匿名信号量放入进程间的共享内存中,具体可参考:
man 3 sem_init
本文链接:https://cs.pynote.net/sf/linux/prog/202208011/
-- EOF --
-- MORE --