triplesheep 发表于 2015-10-10 23:19

【共享内存shmat】关于使用shmat遇到的诡异问题

目前在看书的时候看到进程间通信共享内存的一个例子本来就打算很简单的去linux上调试一下,结果发生非常让我难以理解的问题,我已经纠结一个晚上了。
主要问题是:
1、在shmget和shmat函数都没有问题,但是在使用shmat得到地址后无法对地址进行操作,我是在发现没有看到预期的打印后一步步加打印进行调试的,发现shmat后对addr无法操作。
2、还有一个问题是同一个父进程产生的几个子进程在使用shmat结果会一样吗?我试了几次结果都会一样的。但是看之前有帖子讨论貌似会不一样的。
具体的代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <stdlib.h>
#define SHMKEY                75
int shmid, i;
int *addr;

void CLIENT()
{
        printf("client\n");
        int i = 9;
        shmid = shmget(SHMKEY, 1024, 0777);
        if (-1 == shmid)
        {
                printf("create client key error\n");
        }
        addr = (int *)shmat(shmid, NULL, 0);
        if ((int *)-1 == addr)
        {
                printf("create client addr error\n");
        }
        else
        {
                printf("client addr %p\n", addr);
        }
        for(i = 9; i >= 0; i--)
        {
                printf("client_here1\n");
                while(*addr != -1);
                printf("client_here2\n");
                *addr = i;
                printf("client sent %d\n", *addr);
        }
        printf("out client\n");
        exit(0);
}

void SERVER()
{
        printf("server\n");
        shmid = shmget(SHMKEY, 1024, 0777|IPC_CREAT);
        if (-1 == shmid)
        {
                printf("create server key error\n");
        }
        addr = (int *)shmat(shmid, NULL, 0);
        if ((int *)-1 == addr)
        {
                printf("create server addr error\n");
        }
        else
        {
                printf("server addr %p\n", addr);
        }
        do
        {
                printf("server_here1\n");
                *addr = -1;
                printf("server_here2\n");
                while(*addr == -1);
                printf("server received %d\n", *addr);
        }while(*addr);
        shmctl(shmid, IPC_RMID, 0);//最后一个参数*buf
        printf("out server\n");
        exit(0);
}
void main()
{
        printf("in\n");
        while((i = fork()) == -1);
        if(!i)        SERVER();
        while((i = fork()) == -1);
        if(!i)        CLIENT();
        wait(NULL);
        wait(NULL);
        printf("out\n");
}


ubuntu 12.04调试结果是:
(我一共运行了很多次,截取其中三次)
in
server
server addr 0xfffffffff1d95000
server_here1
client
client addr 0xfffffffff1d95000
client_here1
out
/////////////////////////////////////////////
in
server
server addr 0x1f2c7000
server_here1
client
client addr 0x1f2c7000
client_here1
out
/////////////////////////////////
in
client
client addr 0xffffffff96122000
client_here1
server
server addr 0xffffffff96122000
server_here1
out

跪谢给位大大们的帮助!!!

墙根下的水壶 发表于 2016-04-28 23:06

把你的程序运行了一下,改动三个地方即可:
1. fork的逻辑应该调整成:
                                 if (fork())
                                {
                                        SERVER();
                                }
                                else
                                {
                                        CLIENT();
                                }
    当前代码会嵌套生成过多的进程

2. 头文件需要加上 #include <sys/shm.h>

3. 将SHMID的生成放在main函数中且在fork之前,这样就可以同样被当前进程和子进程同时知道。强制的用75作为SHMKEY并不安全。
实例如下:
          shmid = shmget(IPC_PRIVATE, 1024, S_IRUSR|S_IWUSR);
          if (-1 == shmid)
          {
            printf("create key error\n");
          }

页: [1]
查看完整版本: 【共享内存shmat】关于使用shmat遇到的诡异问题