note
使用信号量进行进程间通信时,信号量要放置在共享内存上;若是线程间通信,放堆上或全局变量区就行
code
// 使用信号量进行进程间通信时,信号量要放置在共享内存上;若是线程间通信,放堆上或全局变量区就行
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <fcntl.h>
const char* shm_obj1 = "shm1";
const char* shm_obj2 = "shm2";
int shm_id1 = -1;
int shm_id2 = -1;
void* shm_handle1 = NULL; // 对应生产量
void* shm_handle2 = NULL; // 对应容纳量
sem_t* sem_cnt = NULL; // 已生产量
sem_t* sem_capcity = NULL; // 可容纳量
const int sem_between_threads = 0; // 线程间通信
const int sem_between_processes = 1; // 进程间通信
// 父进程负责生产
void parent_work(void) {
int ret = -1;
int val = 0;
int i = 0;
for (i = 0; i < 10; i++) {
ret = sem_wait(sem_capcity);
if (ret == -1) {
fprintf(stderr, "parent process sem_wait error,%s\n", strerror(errno));
}
else if (ret == 0) {
(void)sem_getvalue(sem_capcity, &val);
fprintf(stdout, "parent process get sem_capcity value:%d\n", val);
(void)sem_post(sem_cnt);
}
sleep(2);
}
wait(NULL);
(void)sem_destroy(sem_cnt);
(void)sem_destroy(sem_capcity);
(void)shm_unlink(shm_obj1);
(void)shm_unlink(shm_obj2);
exit(EXIT_SUCCESS);
}
// 子进程负责消费
void child_work(void) {
int ret = -1;
int val = 0;
int i = 0;
for (i = 0; i < 10; i++) {
ret = sem_wait(sem_cnt);
if (ret == -1) {
fprintf(stderr, "child process sem_wait error,%s\n", strerror(errno));
}
else if (ret == 0) {
(void)sem_getvalue(sem_cnt, &val);
fprintf(stdout, "child process get sem_cnt value:%d\n", val);
(void)sem_post(sem_capcity);
}
sleep(1);
}
exit(EXIT_SUCCESS);
}
int main(int argc, char** argv) {
int ret = -1;
pid_t pid = 0;
shm_id1 = shm_open(shm_obj1, O_CREAT|O_RDWR, 666);
if (shm_id1 == -1) {
fprintf(stderr, "parent process shm_open shm_obj1 error,%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
shm_id2 = shm_open(shm_obj2, O_CREAT|O_RDWR, 666);
if (shm_id1 == -1) {
fprintf(stderr, "parent process shm_open shm_obj2 error,%s\n", strerror(errno));
(void)shm_unlink(shm_obj1);
exit(EXIT_FAILURE);
}
ftruncate(shm_id1, sizeof(sem_t));
ftruncate(shm_id2, sizeof(sem_t));
shm_handle1 = mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED, shm_id1, 0);
if (shm_handle1 == MAP_FAILED) {
fprintf(stderr, "parent process mmap shm_id1 error,%s\n", strerror(errno));
(void)shm_unlink(shm_obj1);
(void)shm_unlink(shm_obj2);
exit(EXIT_FAILURE);
}
shm_handle2 = mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED, shm_id2, 0);
if (shm_handle2 == MAP_FAILED) {
fprintf(stderr, "parent process mmap shm_id2 error,%s\n", strerror(errno));
(void)shm_unlink(shm_obj1);
(void)shm_unlink(shm_obj2);
exit(EXIT_FAILURE);
}
sem_cnt = shm_handle1;
sem_capcity = shm_handle2;
// 可存储量初始化为10
ret = sem_init(sem_capcity, sem_between_processes, 10);
if (ret == -1) {
fprintf(stderr, "parent process sem_init sem_capcity error,%s\n", strerror(errno));
(void)shm_unlink(shm_obj1);
(void)shm_unlink(shm_obj2);
exit(EXIT_FAILURE);
}
// 已生产量初始化为0
ret = sem_init(sem_cnt, sem_between_processes, 0);
if (ret == -1) {
fprintf(stderr, "parent process sem_init sem_cnt error,%s\n", strerror(errno));
(void)sem_destroy(sem_capcity);
(void)shm_unlink(shm_obj1);
(void)shm_unlink(shm_obj2);
exit(EXIT_FAILURE);
}
pid = fork();
if (pid < 0) {
fprintf(stderr, "parent process fork error,%s\n", strerror(errno));
(void)sem_destroy(sem_cnt);
(void)sem_destroy(sem_capcity);
(void)shm_unlink(shm_obj1);
(void)shm_unlink(shm_obj2);
exit(EXIT_FAILURE);
}
if (pid > 0) {
fprintf(stdout, "i am parent process,pid:%d\n",getpid());
parent_work();
}
else if (pid == 0) {
fprintf(stdout, "i am child process,pid:%d\n",getpid());
child_work();
}
return 0;
}
// sem_init\sem_destroy
test