使用共享内存实现进程间通信 -使用信号实现同步

本文介绍了如何使用共享内存实现进程间通信,并通过信号实现进程间的同步。提供了具体代码实例,展示了父子进程及不同进程间通信的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天,给大家分享一下共享内存实现通信,使用信号实现同步。
1. 进程的创建
1)对于进程的创建,使用的函数为fork();
函数原型为pid_t fork(void);
即可在父进程中创建子进程

  头文件:#include <sys/types.h>
              #include <unistd.h>
    返回值:-1 出错;
                  0 :子进程;
                  子进程的PID(大于0的整数): 父进程
   子进程创建成功之后,就会有自己独立的内存空间,会拷贝父进程内存空间中几乎所有的内容。    
   在这里运行程序时,子进程和父进程会同时去去抢占系统资源,抢占到系统资源的几率相等,所以可以得出父进程和子进程执行的顺序是不确定的,所以这里我们使用信号实现同步,在子进程中使用raise()函数,向自己发送一个SIGSTOP的信号,使子进程暂停;在父进程中调用watpid()函数等待子进程是否结束,如果没有结束,则使用kill(pid,SIGCONT)函数向子进程发送继续执行信号,即可实现同。
   说一下两个函数,getpid();得到自己进程号,
                getppid();得到父进程的进程号

下面这个代码是关于父子进程通信的实现

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main()
{
    key_t key = ftok(".",15);
    if(key<0)
    {
      perror("ftok error");
      return -1;
    }

    int shm=shmget(key,1024,IPC_CREAT|0666);
    if(shm<0)
    {
      perror("shmget error");
      return -1;
    }
    char *p = (char *)shmat(shm,NULL,0);
    if((char *)-1 == p)
    {
      return -1;
    }

   pid_t pid = fork();
   if(pid<0)
   {
     perror("fork error");
     return -1;
   }
   else if(pid == 0)
   {
      while(1)
     {
        if(*p!=0)
        {
          printf("from 十号:%s\n",p);
        }
        memset(p,0,1024);

        printf("库里:");
        gets(p);
        sleep(5);
        raise(SIGSTOP);
     }
   }
   else //waitpid函数 在父进程中返回的是子进程的ID
   {
    while(1) 
    {
        sleep(5);
        if((waitpid(pid,NULL,WNOHANG))==0)
        {
            if(*p!=0)
            {
                printf("from 库里:%s\n",p);
            }
            memset(p,0,1024);
            printf("十号:");
            gets(p);
            sleep(5);
            kill(pid,SIGCONT);
        }
    }
   }
   shmdt(p);
   shmctl(shm,IPC_RMID,NULL);
    return 0;
}

接下来是不同进程之间的通信-使用共享内存以及信号实现同步。
源码pro-chat3.c如下:

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

void funXLD(int sign)
{

}
int main()
{
     //创建共享内存
     key_t key =ftok(".",12);
     if(key<0)
     {
       perror("ftok error");
       return -1;
     }
      int ret = shmget(key,1024,IPC_CREAT | 0666);
      if(ret<0)
      {
        perror("shmget error");
        return -1;
      }
        char *p = shmat(ret,NULL,0);
        if((char *)-1 == p)
        {
         perror("shmat error");
         return -1;
        }
        signal(SIGUSR1,funXLD);

        pid_t pid2 =getpid();
        pid_t pid = *(int *)p;//从内存中获取进程的ID

        memset(p,0,1024);
        *(int *)p = pid2; //将自己的ID放入内存
        kill(pid,SIGUSR1);
         printf("已接通,等待詹姆斯说话\n");
          while(1)
        {
            pause();
            if(*p != 0)
            {
               printf("from 詹姆斯:%s\n",p);
            }
            memset(p,0,1024);
            printf("库里:");
            gets(p);
            if(strcmp(p,"#")==0)
            {
                kill(pid,SIGABRT);
                shmdt(p);
                shmctl(ret,IPC_RMID,NULL);
                exit(0);
            }
            kill(pid,SIGUSR1);
        }
       shmdt(p);
       shmctl(ret,IPC_RMID,NULL);
     return 0;
}

pro-chat4.c如下

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

void funXLD (int sign)
{

}
int main()
{
     //创建共享内存
     key_t key =ftok(".",12);
     if(key<0)
     {
       perror("ftok error");
       return -1;
     }
      int ret = shmget(key,1024,IPC_CREAT | 0666);
      if(ret<0)
      {
        perror("shmget error");
        return -1;
      }
        char *p = shmat(ret,NULL,0);
        if((char *)-1 == p)
        {
         perror("shmat error");
         return -1;
        }
            signal(SIGUSR1,funXLD);

            pid_t pid = getpid();
            memset(p,0,1024);
            *(int *)p = pid;
            printf("连接中。。。\n");
            pause();
            printf("连接成功\n");
            pid = *(int *)p;
          while(1)
        {
            memset(p,0,1024);
            printf("詹姆斯:");
            gets(p);
            if(strcmp(p,"#")==0)
            {
                kill(pid,SIGABRT);
                shmdt(p);
                shmctl(ret,IPC_RMID,NULL);
                exit(0);
            }
            kill(pid,SIGUSR1);
            pause();
            if(p!=NULL)
            {
             printf("from 库里:%s\n",p);
            }

        }
       shmdt(p);

     return 0;
}

有兴趣的可以试试,希望大家可以常来看我的博客。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值