nbzlk 发表于 2022-12-6 10:13

Linux中基于的共享内存的两进程之间的实时通信

两个进程的代码大抵相同,只有对信号量的处理有一点区别。
> 第一次的提示显示有的bug😅
> 还在学习中

**思路:每个进程创建一个自己的线程,这个线程根据信号量来决定是否要进入读取内容的判读,如果进入,则开始进行共享内存中是否有内容,有就取出来,没有就进行下一次的循环。**
### 结果



### a进程源码

```c
#include <stdio.h>
#include <fcntl.h>         /* For O_* constants */
#include <sys/stat.h>      /* For mode constants */
#include <semaphore.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <pthread.h>

#define SHM_SIZE 128

char *p = NULL;
sem_t *sem1 = NULL, *sem2 = NULL;

void fun(int signo)
{
        shmdt(p); // 取消对共享空间的映射
        sem_close(sem1); // 关闭信号量,内核中没有删除
        sem_close(sem2);
        sem_unlink("zlk"); // 删除信号量
        exit(0);
        return ;
}

void *jieshou(void *arg)
{
        while(1)
        {
                // 在阻塞的时候无操作
                sem_wait(sem1);
                if(*p != 0)
                {
                        //printf("收到:%s\r\n", p);
                        printf("收到:%s", p);
                        memset(p, 0, sizeof(SHM_SIZE));
                }
        }
}

int main(int argc, char *argv[])
{
        // 信号量部分
        sem1 = sem_open("shou", O_CREAT, 0666, 0); // 设置信号量sem1的初始化值为0
        if(SEM_FAILED == sem1) // 判断信号量是否创建成功
        {
                perror("sem_open error");
                return -1;
        }
        sem2 = sem_open("fa", O_CREAT, 0666, 0);
        if(SEM_FAILED == sem2) // 判断信号量是否创建成功
        {
                perror("sem_open error");
                return -1;
        }
        // 共享内存部分
        key_t key = ftok(".", 22);
        if(-1 == key)
        {
                perror("ftok error");
                return -1;
        }
        int shmId = shmget(key, SHM_SIZE, IPC_CREAT | 0666); // 生成一个共享空间
        if(-1 == shmId)
        {
                perror("shmget error");
                return -1;
        }
        p = (char *)shmat(shmId, NULL, 0); // 在私有空间中建立共享内存的映射
        if((void *)-1 == p)
        {
                perror("shmat error");
                return -1;
        }
        memset(p, 0, sizeof(SHM_SIZE)); // 清空原先空间里的内容
        printf("--------zlk------------\r\n");

        // 创建一个线程,用于监听收到的信息
        pthread_t tID = -1;
    if(0 != pthread_create(&tID, NULL, jieshou, NULL))
    {
      printf("creater pthread error\r\n");
      return -1;
    }

        while(1)
        {
                signal(SIGINT, fun); // 收到Ctrl + c后调用自定义fun函数
                printf("发送:\r\n");
                fgets(p, SHM_SIZE, stdin);
                sem_post(sem2); // 使sem2加1
        }
        return 0;
}

```

### b进程源码

```c
#include <stdio.h>
#include <fcntl.h>         /* For O_* constants */
#include <sys/stat.h>      /* For mode constants */
#include <semaphore.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <pthread.h>

#define SHM_SIZE 128

char *p = NULL;
sem_t *sem1 = NULL, *sem2 = NULL;

void fun(int signo)
{
        shmdt(p); // 取消对共享空间的映射
        sem_close(sem1); // 关闭信号量,内核中没有删除
        sem_close(sem2);
        sem_unlink("zlk"); // 删除信号量
        exit(0);
        return ;
}

void *jieshou(void *arg)
{
        while(1)
        {
                sem_wait(sem2);
                if(*p != 0)
                {
                        printf("收到:%s", p);
                        memset(p, 0, sizeof(SHM_SIZE));
                }
        }
}

int main(int argc, char *argv[])
{
        // 信号量部分
        sem1 = sem_open("shou", O_CREAT, 0666, 0); // 设置信号量sem1的初始化值为0
        if(SEM_FAILED == sem1) // 判断信号量是否创建成功
        {
                perror("sem_open error");
                return -1;
        }
        sem2 = sem_open("fa", O_CREAT, 0666, 0);
        if(SEM_FAILED == sem2) // 判断信号量是否创建成功
        {
                perror("sem_open error");
                return -1;
        }
        // 共享内存部分
        key_t key = ftok(".", 22);
        if(-1 == key)
        {
                perror("ftok error");
                return -1;
        }
        int shmId = shmget(key, SHM_SIZE, IPC_CREAT | 0666); // 生成一个共享空间
        if(-1 == shmId)
        {
                perror("shmget error");
                return -1;
        }
        p = (char *)shmat(shmId, NULL, 0); // 在私有空间中建立共享内存的映射
        if((void *)-1 == p)
        {
                perror("shmat error");
                return -1;
        }
        printf("--------ylx------------\r\n");
        // 创建一个线程,用于监听收到的信息
        pthread_t tID = -1;
    if(0 != pthread_create(&tID, NULL, jieshou, NULL))
    {
      printf("creater pthread error\r\n");
      return -1;
    }
        while(1)
        {
                signal(SIGINT, fun); // 收到Ctrl + c后调用自定义fun函数
                printf("发送:\r\n");
                fgets(p, SHM_SIZE, stdin);
                sem_post(sem1); // 使sem1加1
        }
        return 0;
}

```

AyyArr 发表于 2022-12-6 11:18

6666可以 可以

netdata 发表于 2022-12-6 12:19


感谢分享!

lfordch 发表于 2022-12-6 12:47

感谢分享,学习了!{:301_1003:}

wuditieniu 发表于 2023-7-12 08:53

学习了,最近正在学习linux进程通信方面的

BinaryHK 发表于 2023-10-31 13:07

感谢分享,,收藏了{:301_993:}

lalala518 发表于 2023-11-2 09:35

感谢分享,学习一下

liuxf09 发表于 2023-12-29 13:56

感谢分享,学习了

sihaitangzhu666 发表于 2024-3-4 20:13

先收藏, 正在搞这方面的
页: [1]
查看完整版本: Linux中基于的共享内存的两进程之间的实时通信