信号量和共享内存
Semaphore and shared memory
我尝试编写一个程序,其中包含 2 个由信号量同步的进程。 parent 进程生成一个随机数并将其保存到共享内存中。 child 读取这个数字。它只有在 parent 完成生成后才能读取,并且 parent 只有在 child 读取它才能生成新号码。
我不知道我的程序是否正确运行,因为当我尝试访问 data->random_num = random;
或 data->random_num;
.
时出现分段错误
密码是:
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
const key_t sem_key = (key_t)0x12345678;
const key_t shm_key = (key_t)0x12339678;
struct shared_data{
int random_num;
};
union semun{
int val; //setval value
};
int sem_wait(int semafor_id){
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = -1;
sb.sem_flg = SEM_UNDO;
return semop(semafor_id,&sb,1);
}
int sem_signal(int semafor_id){
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = 1;
sb.sem_flg = SEM_UNDO;
return semop(semafor_id,&sb,1);
}
int main(int argc,char* argv[]){
int status;
srand(time(NULL));
//Create shared memory
int memory_id = shmget(shm_key,sizeof(struct shared_data),0600|IPC_CREAT|IPC_EXCL);
if(memory_id < 0){
printf("Shared memory creating failed\n");
return 1;
}
//Create semafor
int semafor_id = semget(sem_key,10, 0600|IPC_CREAT|IPC_EXCL);
if(semafor_id < 0){
printf("SEMAFOR creating failed\n");
return 1;
}
semctl(semafor_id,0,SETVAL,1); //init semafor
pid_t pid = fork();
if(pid < 0){
printf("FORK FAILED\n");
}
else if(pid > 0){
printf("PARENT\n");
int i;
if(i = sem_wait(semafor_id) < 0){
printf("Failed wait parent\n");
return 1;
}else{
int random = rand() % 80;
printf("Generate random number: %d\n",random);
//Try attach memory for writting
void* address = shmat(memory_id, NULL ,0);
if(address == NULL){
printf("Failed to atach memory\n");
return 1;
}
struct shared_data* data = (struct shared_data*) address;
data->random_num = random;
if(shmdt(address) != 0){
printf("Failed to detach shared memory\n");
}
sleep(2);
}
if(i = sem_signal(semafor_id) < 0){
printf("Failed signal parent\n");
}else{
printf("Parent leave generating number\n");
}
//wait for child
wait(&status);
printf("Destroy semafor\n");
semctl(semafor_id,0, IPC_RMID,0);
printf("Destroy shared memory\n");
shmctl(memory_id,IPC_RMID, 0);
return 0;
}
else{
printf("CHILD\n");
int j;
//try to get semafor
if(j = sem_wait(semafor_id) < 0){
printf("FAILED wait child\n");
}else{
printf("Child reading data\n");
void* address = shmat(memory_id, NULL ,0);
if(address == NULL){
printf("Failed to atach memory in child\n");
return 1;
}
struct shared_data* data = (struct shared_data*) address;
printf("Child read data %d\n",data->random_num);
sleep(1);
if(shmdt(address) != 0){
printf("Failed to detach shared memory in child\n");
}
}
if(j = sem_signal(semafor_id) < 0){
printf("Failed signal child\n");
}else{
printf("Leave data reading\n");
}
return 0;
}
return 0;
}
void* address = shmat(memory_id, NULL ,0);
我在该行(以及另一个调用 shmat 的地方)收到此错误:
warning: initialization makes pointer from integer without a cast
手册页说 shmat returns 是一个空指针,所以这是一个错误的线索。事实证明,添加这一行(以获取丢失的原型)修复了它:
#include <sys/shm.h>
编辑:以上内容替换了之前的一个转移注意力的答案。
P.S。它有助于在测试时从您的标志中删除 IPC_EXCL ,所以
如果你遇到崩溃,你不必执行 ipcs / ipcrm shuffle
不断地,在你可以之前删除现有的段/信号量
创建新的。
我尝试编写一个程序,其中包含 2 个由信号量同步的进程。 parent 进程生成一个随机数并将其保存到共享内存中。 child 读取这个数字。它只有在 parent 完成生成后才能读取,并且 parent 只有在 child 读取它才能生成新号码。
我不知道我的程序是否正确运行,因为当我尝试访问 data->random_num = random;
或 data->random_num;
.
密码是:
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
const key_t sem_key = (key_t)0x12345678;
const key_t shm_key = (key_t)0x12339678;
struct shared_data{
int random_num;
};
union semun{
int val; //setval value
};
int sem_wait(int semafor_id){
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = -1;
sb.sem_flg = SEM_UNDO;
return semop(semafor_id,&sb,1);
}
int sem_signal(int semafor_id){
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = 1;
sb.sem_flg = SEM_UNDO;
return semop(semafor_id,&sb,1);
}
int main(int argc,char* argv[]){
int status;
srand(time(NULL));
//Create shared memory
int memory_id = shmget(shm_key,sizeof(struct shared_data),0600|IPC_CREAT|IPC_EXCL);
if(memory_id < 0){
printf("Shared memory creating failed\n");
return 1;
}
//Create semafor
int semafor_id = semget(sem_key,10, 0600|IPC_CREAT|IPC_EXCL);
if(semafor_id < 0){
printf("SEMAFOR creating failed\n");
return 1;
}
semctl(semafor_id,0,SETVAL,1); //init semafor
pid_t pid = fork();
if(pid < 0){
printf("FORK FAILED\n");
}
else if(pid > 0){
printf("PARENT\n");
int i;
if(i = sem_wait(semafor_id) < 0){
printf("Failed wait parent\n");
return 1;
}else{
int random = rand() % 80;
printf("Generate random number: %d\n",random);
//Try attach memory for writting
void* address = shmat(memory_id, NULL ,0);
if(address == NULL){
printf("Failed to atach memory\n");
return 1;
}
struct shared_data* data = (struct shared_data*) address;
data->random_num = random;
if(shmdt(address) != 0){
printf("Failed to detach shared memory\n");
}
sleep(2);
}
if(i = sem_signal(semafor_id) < 0){
printf("Failed signal parent\n");
}else{
printf("Parent leave generating number\n");
}
//wait for child
wait(&status);
printf("Destroy semafor\n");
semctl(semafor_id,0, IPC_RMID,0);
printf("Destroy shared memory\n");
shmctl(memory_id,IPC_RMID, 0);
return 0;
}
else{
printf("CHILD\n");
int j;
//try to get semafor
if(j = sem_wait(semafor_id) < 0){
printf("FAILED wait child\n");
}else{
printf("Child reading data\n");
void* address = shmat(memory_id, NULL ,0);
if(address == NULL){
printf("Failed to atach memory in child\n");
return 1;
}
struct shared_data* data = (struct shared_data*) address;
printf("Child read data %d\n",data->random_num);
sleep(1);
if(shmdt(address) != 0){
printf("Failed to detach shared memory in child\n");
}
}
if(j = sem_signal(semafor_id) < 0){
printf("Failed signal child\n");
}else{
printf("Leave data reading\n");
}
return 0;
}
return 0;
}
void* address = shmat(memory_id, NULL ,0);
我在该行(以及另一个调用 shmat 的地方)收到此错误:
warning: initialization makes pointer from integer without a cast
手册页说 shmat returns 是一个空指针,所以这是一个错误的线索。事实证明,添加这一行(以获取丢失的原型)修复了它:
#include <sys/shm.h>
编辑:以上内容替换了之前的一个转移注意力的答案。
P.S。它有助于在测试时从您的标志中删除 IPC_EXCL ,所以 如果你遇到崩溃,你不必执行 ipcs / ipcrm shuffle 不断地,在你可以之前删除现有的段/信号量 创建新的。