在 Posix 中使用共享内存 C 中的信号量等待和信号
Using Shared memory in Posix Semaphore wait and signal in C
以下面这段代码为例。打印后代码停止等待,直到手动停止程序,但不会发出下一个功能的信号。我多次检查它(甚至删除互斥)并发现在 for
或 while
内是导致问题的原因。
根据其他用户的说法,我必须使用 共享内存 才能使其正常工作,但我不知道如何使用它或将其应用于此特定代码。
为了更好地理解这种情况,我查看了很多网站,例如 https://www.geeksforgeeks.org/posix-shared-memory-api/
我看过最推荐的是shmget()
和mmap()
。
所以问题是,我怎样才能 sem_wait()
使用共享内存在任何类型的循环中工作?
#include <stdio.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
sem_t *mutex;
void wait_t(int a)
{
for (int i = 0; i < 3; i++)
{
if (a < 0)
{
sem_wait(&mutex);
printf("waiting\n"); //Stops here due lack of shared memory
}
a--;
}
}
void signal_t(int a)
{
for (int i = 0; i < 3; i++)
{
if (a <= 0)
{
printf("signal\n");
sem_post(&mutex);
}
a++;
}
}
int main()
{
int shared_mem_id = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT);
mutex = shmat(shared_mem_id, NULL, 0);
sem_init(&mutex, 1, 1);
int i = -2;
if(fork() == 0){ // create 1st child process
mutex = shmat(shared_mem_id, NULL, 0);
wait_t(i);
exit(0);
shmdt(mutex);
}
wait(NULL);
if(fork() == 0){ // create 2nd child process
mutex = shmat(shared_mem_id, NULL, 0);
signal_t(i);
exit(0);
shmdt(mutex);
}
wait(NULL);
if(fork() == 0){ // create 3nd child process
mutex = shmat(shared_mem_id, NULL, 0);
signal_t(i);
exit(0);
shmdt(mutex);
}
wait(NULL);
printf("%d\n", i);
exit(0);
}
所以,想法是您的父进程需要创建一个新的共享内存 space:
shared_mem_id = shmemget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT);
那么所有需要访问信号量的进程都需要做:
sem_t *mutex = shmat(shared_mem_id, NULL, 0);
(因此您需要在每个子进程中执行此操作,在 fork 之后)
然后使用信号量的函数将需要访问互斥量指针(记得添加对互斥量的取消引用)。
完成后,每个使用互斥体的进程都需要做:
shmdt(mutex);
当然,您可以随意在共享内存中存储更复杂的结构,只要您分配足够的space。
以下面这段代码为例。打印后代码停止等待,直到手动停止程序,但不会发出下一个功能的信号。我多次检查它(甚至删除互斥)并发现在 for
或 while
内是导致问题的原因。
根据其他用户的说法,我必须使用 共享内存 才能使其正常工作,但我不知道如何使用它或将其应用于此特定代码。
为了更好地理解这种情况,我查看了很多网站,例如 https://www.geeksforgeeks.org/posix-shared-memory-api/
我看过最推荐的是shmget()
和mmap()
。
所以问题是,我怎样才能 sem_wait()
使用共享内存在任何类型的循环中工作?
#include <stdio.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
sem_t *mutex;
void wait_t(int a)
{
for (int i = 0; i < 3; i++)
{
if (a < 0)
{
sem_wait(&mutex);
printf("waiting\n"); //Stops here due lack of shared memory
}
a--;
}
}
void signal_t(int a)
{
for (int i = 0; i < 3; i++)
{
if (a <= 0)
{
printf("signal\n");
sem_post(&mutex);
}
a++;
}
}
int main()
{
int shared_mem_id = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT);
mutex = shmat(shared_mem_id, NULL, 0);
sem_init(&mutex, 1, 1);
int i = -2;
if(fork() == 0){ // create 1st child process
mutex = shmat(shared_mem_id, NULL, 0);
wait_t(i);
exit(0);
shmdt(mutex);
}
wait(NULL);
if(fork() == 0){ // create 2nd child process
mutex = shmat(shared_mem_id, NULL, 0);
signal_t(i);
exit(0);
shmdt(mutex);
}
wait(NULL);
if(fork() == 0){ // create 3nd child process
mutex = shmat(shared_mem_id, NULL, 0);
signal_t(i);
exit(0);
shmdt(mutex);
}
wait(NULL);
printf("%d\n", i);
exit(0);
}
所以,想法是您的父进程需要创建一个新的共享内存 space:
shared_mem_id = shmemget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT);
那么所有需要访问信号量的进程都需要做:
sem_t *mutex = shmat(shared_mem_id, NULL, 0);
(因此您需要在每个子进程中执行此操作,在 fork 之后)
然后使用信号量的函数将需要访问互斥量指针(记得添加对互斥量的取消引用)。
完成后,每个使用互斥体的进程都需要做:
shmdt(mutex);
当然,您可以随意在共享内存中存储更复杂的结构,只要您分配足够的space。