我必须解决生产者和消费者的问题。我只能使用 POSIX(没有 System V)。我现在采取一些小步骤并尝试与子进程实现简单的共享。不幸的是,child 无法向 fifo 添加任何内容。
typedef struct elem{
int val;
bool a;
bool b;
bool c;
struct elem * next;
} elem_t;
typedef struct fifo
{
elem_t * head;
elem_t * tail;
int size;
}fifo_t;
fifo_t* add_elem( fifo_t*, const int);
fifo_t* remove_elem( fifo_t*);
fifo_t* init(void);
void list_print( const fifo_t* );
void list_print_elem(const elem_t* );
int main()
{
int fd;
void *addr;
fifo_t * queue = NULL;
queue = init();
add_elem(queue,5);
add_elem(queue,8);
list_print(queue);
remove_elem(queue);
list_print(queue);
fd = shm_open("/test", O_CREAT | O_EXCL | O_RDWR, 0666);
size_t size_fifo = sizeof queue;
ftruncate(fd,size_fifo);
addr = mmap(NULL, size_fifo, PROT_READ | PROT_WRITE,MAP_SHARED ,fd, 0);
pid_t pidA = fork();
if(pidA==0){
fifo_t * q = (fifo_t*) addr;
add_elem(q,5);
exit(0);
}
else{
int status;
waitpid(pidA, &status, 0);
list_print(queue);
}
munmap(addr,size_fifo);
shm_unlink("/test");
return 0;
}
和方法添加:
fifo_t * add_elem(fifo_t* s, int i)
{
elem_t* p = malloc( 1 * sizeof(*p) );
if( NULL == p )
{
fprintf(stderr, "IN %s, %s: malloc() failed\n", __FILE__, "list_add");
return s;
}
p->val = i;
p->next = NULL;
if( NULL == s )
{
printf("Queue not initialized\n");
free(p);
return s;
}
else if( NULL == s->head && NULL == s->tail )
{
/* printf("Empty list, adding p->num: %d\n\n", p->num); */
s->head = s->tail = p;
s->size +=1;
return s;
}
else
{
/* printf("List not empty, adding element to tail\n"); */
s->tail->next = p;
s->tail = p;
s->size +=1;
}
return s;
}
我的输出是这样的:
主进程可以添加和删除元素。 child 应该添加 val =5 并增加大小,但它没有成功。 有人可以解释我的错误吗?
最佳答案
发布的代码的前几行使用堆栈上的队列,该队列是通过调用 init()
进行初始化的。
调用 mmap()
后,新队列被定义为位于通过调用 mmap()
分配的内存中。
发布的代码无法初始化该新队列。
然后在调用fork()
之后,子进程尝试将一个条目添加到由mmap()
分配的内存中的(未初始化的)队列中因此,自然地,该条目不在堆栈上的队列中
对 list_print()
的调用会传递一个指向堆栈上队列的参数。因此永远不会看到 mmap() 分配的内存中的条目
关于子进程无法写入共享内存(fifo - c 中的链表),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47560994/