IPC通过共享内存和管道给出分段错误:11 in C

问题描述 投票:0回答:1

我正在尝试在父子进程之间共享文件。父级通过管道发送文件,子级将该行写入共享内存,以便父级可以通过共享内存读取和打印文件。但是,我遇到了分段错误:11.此外,我做了类似下面的代码的操作,但是那一次我无法获得正确的内容,甚至每次调用都得到不同的结果。

我不确定要增加指针部分。但是,最好多花点时间看一下代码。

编辑:我将char *更正为char [],现在分割错误消失了。但是,每次运行都会得到不同的结果,在输出中会看到一些额外的字符。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>

#define SHM_NAME_1 "Child 1"

int main(){

    pid_t pid;
    FILE *file;
    char *infile = "in.txt";

    pid = fork();

    if(pid < 0){
        fprintf(stderr, "Fork failed\n");
        return 1;
    }

    if(pid > 0){ // parent

        file = fopen(infile, "r");

        if(file == 0){
            fprintf(stderr, "File failed\n");
            return 1;
        }
        // close read end of pipe
        mknod("FIFO", S_IFIFO | 0666, 0);
        int fd = open("FIFO", O_WRONLY);

        char str[300];
        while(fgets(str, sizeof(str), file) > 0)
        {
            // write all lines of file
            write(fd, str, strlen(str));
        }
        // close file and pipe
        close(fd);
        fclose(file);
        // wait for child to write to shared memory
        wait(NULL);

        // open shared segment
        int shm_first = shm_open(SHM_NAME_1, O_RDONLY, 0666);

        if (shm_first == -1) {
            fprintf(stderr, "Failed: Shared Memory 1");
            exit(-1);
        }

        // create memory pointer
        void *ptr = mmap(0,4096, PROT_READ, MAP_SHARED, shm_first, 0);

        if (ptr == MAP_FAILED) {
            printf("Map failed 1\n");
            return -1;
        }
        // print out result and unlibk shared segment
        fprintf(stdout, "Normal input: \n%s\n", ptr);
        shm_unlink(SHM_NAME_1);

    } else { // child

        // create the shared segment for the first time
        int shm_child_1 = shm_open(SHM_NAME_1, O_CREAT | O_RDWR, 0666);

        // configure the size of the shared memory segment 
        ftruncate(shm_child_1,4096);
        // map the pointer to the segment
        void *ptr_child_1 = mmap(0,4096, PROT_READ | PROT_WRITE, MAP_SHARED, shm_child_1, 0);

        if (ptr_child_1 == MAP_FAILED) 
        {
            printf("Map failed in first child\n");
            return -1;
        }


        mknod("FIFO", S_IFIFO | 0666, 0);
        int fd = open("FIFO", O_RDONLY);

        int num;
        char s[300];
        while((num = read(fd, s, sizeof(s)))> 0)
        {     
            sprintf(ptr_child_1, "%s", s);
            ptr_child_1 += num;
        }

        close(fd);
        exit(0);

    }

    return 0;
}
c memory pipe ipc shared
1个回答
1
投票

快速观察。

在下面的代码中,您有一个未初始化为指向任何内容的char指针。这导致fget将其从file读取的内容复制到内存中的任意位置。

    char *str;
    while(fgets(str, 100, file) > 0)

现在缓冲区问题已解决,以下表达式中的花括号也有问题

    while((num = read(fd, s, sizeof(s)) > 0))

num将为1或0,而不是读取的字节数或eof为0。这应该是

    while((num = read(fd, s, sizeof(s))) > 0)

一旦读取了字节数,则需要将终端终止为零。因为您使用的sprintf期望%s的参数为零终止字符串。

    while((num = read(fd, s, sizeof(s)))> 0)
    {
        s[num] = '\0';  // Terminate the string to the number of bytes read
        sprintf(ptr_child_1, "%s", s);
        ptr_child_1 += num;
    }
© www.soinside.com 2019 - 2024. All rights reserved.