英文:
Unable to call sem_trywait function in consumer process while able to get POSIX semaphore value
问题
I am currently trying to solve issue with my multi-process project. In the process called sender(file sender.c, producer) I am able to modify unnamed semaphore value bu using sem_wait and sem_post functions, POSIX sempahore is in shared memory. Curiously, in the process called receiver.c(consumer), I am able to get semaphore value, but calling sem_trywait gives me segmentation fault error.
我目前正在尝试解决我的多进程项目中的问题。在名为sender(文件sender.c,生产者)的进程中,我能够使用sem_wait和sem_post函数来修改无名信号量的值,POSIX信号量位于共享内存中。但奇怪的是,在名为receiver.c(消费者)的进程中,我能够获取信号量的值,但调用sem_trywait会导致分段错误。
I am suspecting some issues with passing arguments(pass-by-reference vs. pass-by-value). Other cause of issue might be due to improper way of releasing/destroing semaphore - i am aware that currently this issue might not be solved properly. Both sender.c and receiver.c get the data structure (buffer_node struct) from static linking.
我怀疑传递参数时存在一些问题(按引用传递与按值传递)。问题的另一个原因可能是释放/销毁信号量的方式不正确 - 我意识到目前这个问题可能没有得到正确解决。sender.c和receiver.c都从静态链接中获取数据结构(buffer_node结构)。
Header file(only struct buffer_node is tested)
头文件(只测试了结构体buffer_node)
Sender process:
发送进程:
Receiver process:
接收进程:
Any help would be appreciated.
任何帮助将不胜感激。
英文:
I am currently trying to solve issue with my multi-process project. In the process called sender(file sender.c, producer) I am able to modify unnamed semaphore value bu using sem_wait and sem_post functions, POSIX sempahore is in shared memory. Curiously, in the process called receiver.c(consumer), I am able to get semaphore value, but calling sem_trywait gives me segmentation fault error.
I am suspecting some issues with passing arguments(pass-by-reference vs. pass-by-value). Other cause of issue might be due to improper way of releasing/destroing semaphore - i am aware that currently this issue might not be solved properly. Both sender.c and receiver.c get the data structure (buffer_node struct) from static linking.
I tested that code on both Ubuntu running on x64 processor and Raspbian(Raspberry PI) running on ARM processor, i also tried changing sem_trywait to sem_wait. Preferably, I would like to avoid changing to named semaphores.
Header file(only struct buffer_node is tested)
#define _CBUFFAPI_H_
#include <stdlib.h>
#include <signal.h>
#include "stdio.h"
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/mman.h>
#include <assert.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFFER_SIZE 5
#define SAMPLES_AMOUNT 240
struct buffer_node {
unsigned long int buffered_samples[SAMPLES_AMOUNT];
sem_t semaphore;
int sem_val;
};
struct cyclic_buffer {
struct buffer_node buffer_elements[BUFFER_SIZE];
unsigned int head;
unsigned int tail;
unsigned int full;
unsigned int max;
};
/*cyclic_buffer* init_buffer();
//void buffer_reset(cyclic_buffer* cb);
//void buffer_free(cyclic_buffer* cb);
//void buffer_put(cyclic_buffer* cb, unsigned int index);
//unsigned int is_buffer_full(cyclic_buffer* cb);*/
int get_sem_val(sem_t sem);
#endif
Sender process:
#include <stdlib.h>
#include <signal.h>
#include "stdio.h"
#include <semaphore.h>
#include "cbuffapi.h"
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/types.h>
#include <assert.h>
#include <sys/stat.h>
#include <fcntl.h>
#define NAME "/testmem"
struct buffer_node * shm_buffer;
void Handler(int signo)
{
//System Exit
printf("\r\n END \r\n");
sem_close(&(shm_buffer->semaphore));
munmap(0, sizeof(struct buffer_node));
shm_unlink(NAME);
exit(0);
}
int main()
{
signal(SIGINT, Handler);
int shm_cyclic_buffer_fd = shm_open(NAME, O_CREAT|O_RDWR|O_EXCL, 0666);
if(shm_cyclic_buffer_fd < 0)
{
perror("shm_open()");
return 1;
}
ftruncate(shm_cyclic_buffer_fd, sizeof(struct buffer_node));
shm_buffer = (struct buffer_node*)mmap(0, sizeof(struct buffer_node), PROT_WRITE|PROT_READ, MAP_SHARED, shm_cyclic_buffer_fd, 0);
shm_buffer->sem_val = 67;
sem_init(&(shm_buffer->semaphore), 1, 4);
int test_sem_val = 15;
while(1)
{
if(sem_trywait(&(shm_buffer->semaphore))==0)
{
sem_getvalue(&(shm_buffer->semaphore), &test_sem_val);
printf("%d\n", test_sem_val);
shm_buffer->sem_val = shm_buffer->sem_val + 1;
printf("%d\n", shm_buffer->sem_val);
sleep(5);
sem_post(&(shm_buffer->semaphore));
sem_getvalue(&(shm_buffer->semaphore), &test_sem_val);
printf("%d\n", test_sem_val);
}
else if(sem_trywait(&(shm_buffer->semaphore))== -1)
{
printf("variable reading - overwriting impossible\n");
}
sleep(0.5);
}
return 0;
}
Receiver process:
#include <stdlib.h>
#include <signal.h>
#include "stdio.h"
#include <semaphore.h>
#include "cbuffapi.h"
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/types.h>
#include <assert.h>
#include <sys/stat.h>
#include <fcntl.h>
#define NAME "/testmem"
int shared_memory_fd;
void Handler(int signo)
{
//System Exit
printf("\r\n END \r\n");
munmap(0, sizeof(struct buffer_node));
close(shared_memory_fd);
shm_unlink(NAME);
exit(0);
}
int main()
{
signal(SIGINT, Handler);
struct buffer_node* shm_buffer;
int shared_memory_fd = shm_open(NAME, O_RDONLY, 0666);
if(shared_memory_fd < 0)
{
perror("Impossible to get shared memory file descriptor");
return 1;
}
printf("Shared memory ID ok\n");
//memory mapping
shm_buffer=(struct buffer_node*)mmap(0, sizeof(struct buffer_node), PROT_READ, MAP_SHARED, shared_memory_fd, 0);
if(shm_buffer == (void *) -1)
{
perror("Cannot attach to shared memory");
return 2;
}
printf("map ok");
printf("shared memory ID ok\n");
int test_sem_val = 1;
while(1)
{
sem_getvalue(&(shm_buffer->semaphore), &test_sem_val);
printf("%d\n", test_sem_val);
printf("%d\n", shm_buffer->sem_val);
sleep(5);
if(sem_trywait(&(shm_buffer->semaphore)) == 0)
{
printf("%d\n", shm_buffer->sem_val);
sleep(1);
sem_post(&(shm_buffer->semaphore));
}
else
{
printf("variable modified\n");
sleep(1);
}
}
return 0;
}
Any help would be appreciated.
答案1
得分: 1
接收进程以只读模式 (O_RDONLY
) 打开共享内存对象,并且该对象通过 mmap()
进行映射,使用只读保护(未设置 PROT_WRITE
)。
共享内存中包含一个有效的 sem_t
信号量对象,但由于接收进程中的内存是只读的,任何接收进程尝试修改信号量对象的操作都会导致向该进程发送 SIGSEGV
信号。该信号的默认操作是以核心转储的方式终止进程。
sem_wait()
、sem_trywait()
、sem_timedwait()
和 sem_post()
函数都需要对信号量进行写访问。而 sem_getvalue()
函数仅需要对信号量进行读访问。
英文:
The receiver process is opening the shared memory object in read-only mode (O_RDONLY
) and the object is being mapped by mmap()
with read-only protection (PROT_WRITE
is not set).
The shared memory contains a valid sem_t
semaphore object, but because the memory is read-only in the receiver process, any attempts by the receiver process to modify the semaphore object will result in a SIGSEGV
signal being delivered to the process. The default action for that signal is to terminate the process with a core dump.
The sem_wait()
, sem_trywait()
, sem_timedwait()
and sem_post()
functions all require write access to the semaphore. The sem_getvalue()
function only requires read access to the semaphore.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论