【问题标题】:Why am i getting segmentation fault when trying IPC using shared memory in c linux为什么在 c linux 中尝试使用共享内存的 IPC 时出现分段错误
【发布时间】:2020-11-03 01:01:10
【问题描述】:

问题:在 3 个进程之间实现 IPC,第一个进程创建共享内存,然后向第二个和第三个进程发送信号,以便它们可以连接到该共享内存,现在让第二个进程向共享内存,然后让它向第三个进程发送信号,以便第三个进程读取第二个进程写入的内容。

我的代码:

#include <signal.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <sys/types.h> 
#include <unistd.h> 

static int pid0, pid1, pid2, shmid, status;

struct memory { 
    char msg[100];
}; 

struct memory* shmptr; 
struct sigaction act0, act1, act2;

// Handler For P0
void handler0(int signum) 
{ 
    if (signum == SIGUSR1) { 
        printf("Allowing P1 And P2 To Get Attached\n\n");
        kill(pid1, SIGUSR1); // Allow P1 To Get Attached
        kill(pid2, SIGUSR1); // Allow P2 To Get Attached
    } 

    if (signum == SIGUSR2) { 
        kill(pid1, SIGINT); // Kill P1 
        kill(pid2, SIGINT); // Kill P2 
    } 
} 

// Handler For P1
void handler1(int signum) 
{ 
    if (signum == SIGUSR1) { 
        
        // Attaching To The Shared Memory 
        shmptr = (struct memory*) shmat(shmid, 0, 0); 

        printf("P1 - Attached to: %d\n\n", shmid); 
    } 
} 

// Handler For P2
void handler2(int signum) 
{ 
    if (signum == SIGUSR1) { 
        
        // Attaching To The Shared Memory 
        shmptr = (struct memory*) shmat(shmid, 0, 0); 

        printf("P2 - Attached to: %d\n\n", shmid); 
    } 

    if (signum == SIGUSR2) { 

        printf("Message Read From Shared Memory Is: "); 
        puts(shmptr->msg); 

        status = 1;

        // Detaching P2 From The Shared Memory
        shmdt((void*)shmptr);
        
        kill(pid0, SIGUSR2);
    }
} 

int main() 
{
    status = 0;

    printf("P0\n\n");

    pid0 = getpid();

    // Key Of Shared Memory 
    key_t key = 123456;

    // Shared Memory Creation
    printf("Creating Shared Memory\n\n"); 
    shmid = shmget(key, sizeof(struct memory), IPC_CREAT | 0666); 

    // Attaching P0 To The Shared Memory 
    shmptr = (struct memory*)shmat(shmid, 0, 0); 
    printf("P0 - Attached to: %d\n\n", shmid);

    // Attaching Handler Function To Signal SIGUSR1 For Process 0
    act0.sa_handler = handler0;
    sigaction(SIGUSR1, &act0, NULL);
    printf("Forking...\n\n");
    
    pid1 = vfork();

    if(pid1 == 0){ // Inside P1

        printf("P1\n\n");
        
        // Attaching Handler Function To Signal SIGUSR1 For Process 1
        act1.sa_handler = handler1;
        sigaction(SIGUSR1, &act1, NULL);

        pid2 = vfork();

        if(pid2 == 0){ // Inside P2

            printf("P2\n\n");

            // Attaching Handler Functions To Signals SIGUSR1 And SIGUSR2 For Process 2
            act2.sa_handler = handler2;
            sigaction(SIGUSR1, &act2, NULL);
            sigaction(SIGUSR2, &act2, NULL);
            kill(pid0, SIGUSR1); // Tell P0 That P1 And P2 Are Ready To Get Attached To The Shared Memory
            
        } else { // Inside P1

            printf("P1 Again\n\n");

            // Writing A Message To The Shared Memory
            printf("Enter A Message: \n");
            fgets(shmptr->msg, 100, stdin); 

            // Sending The Message To Process 2
            kill(pid2, SIGUSR2); 
            printf("Sent Message To P2\n\n"); // this gets printed and then a segmentation fault error occurs
        }

    } else { // Inside P0
    
        printf("P0 - Waiting..\n\n");
        while(1){
            if(status == 1)
                break;
        }
        // Detaching P0 From The Shared Memory
        shmdt((void*)shmptr);

        shmctl(shmid, IPC_RMID, (struct shmid_ds *) NULL);
    }
}

执行printf("Sent Message To P2\n\n"); 后我得到一个分段错误错误

请告诉我为什么,我想不通

谢谢

【问题讨论】:

  • 您是否在调试器中运行过代码?
  • 与您的问题无关,但要打印指针(实际上是void * 指针)使用printf 格式%p。格式说明符和类型不匹配会导致未定义的行为。
  • 如果 P1 在 P2 到达 sigaction(SIGUSR2, &amp;act2, NULL) 之前到达 kill(pid2, SIGUSR2),您认为会发生什么?
  • 另一个更不相关的注释:而不是像while (1) { if (condition) break; } 这样的循环,为什么不while (!condition) {}
  • P0 从不分配pid2,所以kill(pid2, SIGUSR1)kill(pid2, SIGINT) 实际上是kill(0, X)

标签: c linux segmentation-fault ipc


【解决方案1】:

vfork() 无法做到这一点。

阅读手册页,尤其是靠近顶部的部分

如果进程由 vfork() 要么修改 pid_t 类型的变量以外的任何数据 用于存储来自 vfork() 的返回值,或从 调用 vfork() 的函数,或调用任何其他函数 在成功调用 _exit(2) 或 exec(3) 系列之一之前 功能。

【讨论】:

  • 非常感谢,我将 pid2 分配移动到属于 p0 的 else 分支并使用 fork 而不是 vfork 并且它有效
猜你喜欢
  • 1970-01-01
  • 2018-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多