Linux:父子进程使用共享内存通信,包含创建和释放共享内存操作

测试程序:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/un.h>

#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>

#if 0
int main(void *arg)
{
int shmid = -1;

shmid = shmget(0x0002, 256, 0644 | IPC_CREAT | IPC_EXCL);//获取内存分配的进程id
if (-1 == shmid)
{
    perror("create shm failed ...");
    return(-1);
}

printf("create shm ok\n");

char *buf = NULL;
buf = (char *)shmat(shmid, NULL, SHM_RND); //共享内存同进程关联,并获取共享内存文件描述符buf.
if ((char *)-1 == buf)
{
    perror("shmat failed ...");
    return(-1);
}

memcpy(buf, "hello world", sizeof("hello world"));

printf("buf is: %s\n", buf);

getchar();  //暂停一下进程,回车键继续执行

shmdt(buf);//shimid共享内存同进程脱离

printf("finish  dt    \n");

getchar();//暂停一下进程,回车键继续执行

int ret = shmctl(shmid, IPC_RMID, NULL); //把shimid共享内存标志为即将删除,当操作过它的进程都退出时,系统会删除该共享内存
if ((void *)-1 == buf)
{
    perror("shmctl failed ...");
    return(-1);
}

return 0;

}
#endif

#if 1
int main(int * argc, const char * argv[])
{
key_t key = IPC_PRIVATE;
int shmid = shmget(0x1002, 512, 0644 |IPC_CREAT | IPC_EXCL);
if(shmid == -1) perror(“shmget fail with: \n”);
char *shmfp = NULL;
shmfp = (char *)shmat(shmid, NULL, SHM_RND);
memcpy(shmfp,“hello world”,sizeof(“hello world”));
printf(“shmfp content is: %s\n”, shmfp);

int i = 0;
pid_t pid;
for(i =0; i < 2; i++)
{
    pid = fork();
    if(pid == 0) break;
}
if(pid == 0) //子进程逻辑
{
    if(i == 0) {
        memcpy(shmfp,"child0 say hello world",sizeof("child0 say hello world"));
        printf("shmfp content is: %s\n", shmfp);
    } else if(i == 1)
    {
        memcpy(shmfp,"child1 say hello world",sizeof("child1 say hello world"));
        printf("shmfp content is: %s\n", shmfp);            
    }

} else if(pid > 0)
{
    memcpy(shmfp,"father say hello world",sizeof("father say hello world"));
    printf("shmfp content is: %s\n", shmfp);   

}
if(pid == 0)
{
    getchar();  //暂停一下进程,回车键继续执行

    shmdt(shmfp);//shimid共享内存同进程脱离

    printf("pid %d finish  dt    \n", getpid());

    getchar();//暂停一下进程,回车键继续执行

    int ret = shmctl(shmid, IPC_RMID, NULL); //把shimid共享内存标志为即将删除,当操作过它的进程都退出时,系统会删除该共享内存

    printf("pid %d finish  把shimid共享内存标志为即将删除   \n", getpid());

    if ((void *)-1 == shmfp)
    {
        perror("shmctl failed ...");
        return(-1);
    }
}
if(pid > 0) //父进程退出前回收子进程
{   while(1) 
    {
        sleep(1);
        int status = -1;
        //int ret =  waitpid(-1,&status,WNOHANG);
        int ret =  wait(&status);//阻塞等待子进程退出
        if(WIFEXITED(status)) printf("recycle child , status:%d\n", WEXITSTATUS(status));
        if(WIFSIGNALED(status)) printf("recycle child , with status:%d\n", WTERMSIG(status));
        if(status == 0) break;//当status为0时,子进程回收完毕,父进程退出循环。
    }
    getchar();  //暂停一下进程,回车键继续执行

    shmdt(shmfp);//shimid共享内存同进程脱离

    printf("pid %d finish  dt    \n", getpid());

    getchar();//暂停一下进程,回车键继续执行

    int ret = shmctl(shmid, IPC_RMID, NULL); //把shimid共享内存标志为即将删除,当操作过它的进程都退出时,系统会删除该共享内存

    printf("pid %d finish  把shimid共享内存标志为即将删除   \n", getpid());     
}
return 0;    

}
#endif

结果:

启动3个进程:
在这里插入图片描述
查看进程id
在这里插入图片描述
查看shm资源 nattch为3
在这里插入图片描述
回车6次删除共享内存,nattch引用依次减小。
在这里插入图片描述
三个进程运行结束后共享内存资源被释放
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个典型的子进程共享内存通信的程序设计问题。您可以使用 Linux 操作系统提供的共享内存函数来实现该程序,例如 shmget、shmat、shmdt、shmctl 等函数。 首先在进程里调用 shmget 函数创建一个共享内存区域,并返回一个共享内存标识符;然后调用 shmat 函数将该共享内存区域附加到进程的地址空间,得到共享内存段的指针;接着在子进程里调用 shmat 函数将该共享内存区域也附加到子进程的地址空间,得到共享内存段的指针,从而实现进程间的共享内存通信子进程可以向共享内存中写入信息,进程可以从共享内存中读取信息并进行显示。 注意,共享内存的大小应当足够存储您需要传递的信息。 如果您需要更详细的代码实现,请参考下面的 C 语言示例代码: ``` #include <stdio.h> #include <stdlib.h> #include <sys/shm.h> #include <sys/types.h> #include <sys/ipc.h> #include <unistd.h> #define SHMSZ 27 // 共享内存的大小 int main() { int shmid; char *shm, *s; // 创建共享内存 if ((shmid = shmget(IPC_PRIVATE, SHMSZ, IPC_CREAT | 0666)) < 0) { perror("shmget"); exit(1); } // 将共享内存附加到进程的地址空间 if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) { perror("shmat"); exit(1); } // 创建子进程 pid_t child_pid = fork(); if (child_pid == -1) { perror("fork"); exit(1); } if (child_pid == 0) { // 子进程 for (s = shm; *s != '\0'; s++) *s = '*'; exit(0); } else { // 进程 wait(NULL); // 等待子进程结束 for (s = shm; *s != '\0'; s++) putchar(*s); putchar('\n'); } // 解除共享内存的附加 if (shmdt(shm) == -1) { perror("shmdt"); exit(1); } // 删除共享内存 if (shmctl(shmid, IPC_RMID, 0) == -1) { perror("shmctl"); exit(1); } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值