第7天 进程间通信

进程间通信

ftok
k的使用

1,如果两个参数相同,那么产生的 key 值也相同。

2,第一个参数一般取进程所在的目录,因为在一个项目中需要通信的几个进程通常会

出现在同一个目录当中。

3,如果同一个目录中的进程需要超过 1 个 IPC 对象,可以通过第二个参数来标识。

4,系统中只有一套 key 标识,也就是说,不同类型的 IPC 对象也不能重复。

进程间通信
c 复制代码
#include "head.h" 

int main(int argc,char *argv[])
{
    // 1、获取键值
    //      (1) 如果两个参数相同,那么产生的key值也相同。
    //      (2) 第一个参数一般取进程所在的目录,因为在一个项目中需要通信的几个进程通常会
    //          出现在同一个目录当中。
    //      (3) 如果同一个目录中的进程需要超过1个IPC对象,可以通过第二个参数来标识。
    //      (4) 系统中只有一套key标识,也就是说,不同类型的IPC对象也不能重复。
    key_t key = ftok(".", 1);

    // 2、获取共享内存ID
    int shmid = shmget(key, 1024, IPC_CREAT | 0644);

    // 3、实现内存映射
    //   NULL 代表系统自动寻找合适内存进行映射
    //   0    代表映射的这块区域我可读可写
    char* ptr = shmat(shmid, NULL, 0);

    // 4、给共享内存写入数据
    char buf[] = "0123456789";

    // 下面这段代码只使用了共享内存中的一个字节
    // 注意目的是为了验证共享内存在没有信号量等机制保证时,内存数据会出现践踏。
    int i = 0;
    while(1)
    {
        *ptr = buf[i++];
        if (i == 10)
        {
            i = 0;
        }
    }

    return 0;
}
复制代码
#include "head.h" 

int main(int argc,char *argv[])
{
    // 1、获取键值
    //      (1) 如果两个参数相同,那么产生的key值也相同。
    //      (2) 第一个参数一般取进程所在的目录,因为在一个项目中需要通信的几个进程通常会
    //          出现在同一个目录当中。
    //      (3) 如果同一个目录中的进程需要超过1个IPC对象,可以通过第二个参数来标识。
    //      (4) 系统中只有一套key标识,也就是说,不同类型的IPC对象也不能重复。
    key_t key = ftok(".", 1);

    // 2、获取共享内存ID
    int shmid = shmget(key, 1024, IPC_CREAT | 0644);

    // 3、实现内存映射
    //   NULL 代表系统自动寻找合适内存进行映射
    //   0    代表映射的这块区域我可读可写
    char* ptr = shmat(shmid, NULL, 0);

    // 4、给共享内存写入数据
    while(1)
    {
        printf("%c", *ptr);
    }

    return 0;
}
c 复制代码
#include "head.h"

struct msgbuf
{
    long mtype;
    char str1[255];
    char str2[255];
};

int main(int argc,char *argv[])
{
    // 1、获取key值,当前key在整个IPC中是通用的
    key_t key = ftok(".", 2);

    // 2、获取消息队列的ID
    int msgid = msgget(key, IPC_CREAT | 0644);

    // 3、组装消息,然后发送
    struct msgbuf buf;
    
    buf.mtype = 1L;

    bzero(buf.str1, sizeof(buf.str1));
    bzero(buf.str2, sizeof(buf.str2));
    fgets(buf.str1, sizeof(buf.str1), stdin);
    fgets(buf.str2, sizeof(buf.str2), stdin);

    msgsnd(msgid, &buf, sizeof(buf), 0); // 0 表示阻塞等待

    return 0;
}
c 复制代码
#include "head.h"

struct msgbuf
{
    long mtype;
    char str1[255];
    char str2[255];
};

int main(int argc,char *argv[])
{
    // 1、获取key值,当前key在整个IPC中是通用的
    key_t key = ftok(".", 2);

    // 2、获取消息队列的ID
    int msgid = msgget(key, IPC_CREAT | 0644);

    // 3、初始化结构体,然后接收数据
    struct msgbuf buf;
    bzero(buf.str1, sizeof(buf.str1));
    bzero(buf.str2, sizeof(buf.str2));

    msgrcv(msgid, &buf, sizeof(buf), 1L, 0); // 0 表示阻塞等待

    puts(buf.str1);
    puts(buf.str2);

    return 0;
}
复制代码
   #include "head.h"

   #define DATA  0   // 用于表示信号量元素的下标
   #define SPACE 1

   /* 函数功能:初始化一个信号量元素
    * 参数1:   信号量的ID
    * 参数2:   当前信号量元素的下标
    * 参数3:   在这块我们使用SETVAL,表示给信号量元素设置初值
    * 参数4:   给信号量元素设置的具体值
    */
   void init_sem(int id, int num, int val)
   {
       semctl(id, num, SETVAL, val);
   }

   /* 函数功能:通过信号量元素的设备,执行P操作
    * 参数1:   信号量的ID
    * 参数2:   当前信号量元素的下标
    */
   void sem_p(int id, int num)
   {
       struct sembuf buf[1];
       buf[0].sem_num = num;  // 信号量元素的下标
       buf[0].sem_op = -1;    // 执行P操作
       buf[0].sem_flg = 0;    // 通常不使用

       // 执行P操作
       semop(id, buf, 1); // 1 代表数组中元素的个数
   }

   /* 函数功能:通过信号量元素的设备,执行V操作
    * 参数1:   信号量的ID
    * 参数2:   当前信号量元素的下标
    */
   void sem_v(int id, int num)
   {
       struct sembuf buf[1];
       buf[0].sem_num = num;  // 信号量元素的下标
       buf[0].sem_op =  1;    // 执行V操作
       buf[0].sem_flg = 0;    // 通常不使用

       // 执行V操作
       semop(id, buf, 1); // 1 代表数组中元素的个数
   }

   int main(int argc,char *argv[])
   {
   /************************* 共享内存操作 **********************/

       // 1、获取键值,提供给共享内存使用
       key_t key = ftok(".", 3);

       // 2、获取共享内存ID
       int shmid = shmget(key, 1024, IPC_CREAT | 0644);

       // 3、实现内存映射
       char* ptr = shmat(shmid, NULL, 0);

   /************************* 信号量操作 **********************/
       
       // 4、获取键值,提供给信号量使用
       key_t sem_key = ftok(".", 4);

       // 5、获取信号量的ID
       //    第二个参数用于表示信号量元素的个数
       int semid = semget(key, 2, IPC_CREAT | 0644);

       // 6、初始化两个信号量元素
       init_sem(semid, DATA,  0); // 初始化无数据
       init_sem(semid, SPACE, 1); // 初始化有资源

       // 7、给共享内存写入数据
       char buf[] = "0123456789";

       // 下面这段代码只使用了共享内存中的一个字节
       // 注意目的是为了验证共享内存在没有信号量等机制保证时,内存数据会出现践踏。
       int i = 0;
       while(1)
       {
           // 8、执行P操作,申请资源,增加数据
           sem_p(semid, SPACE);

           *ptr = buf[i++];
           if (i == 10)
           {
               i = 0;
           }

           // 9、资源减少,数据增加
           sem_v(semid, DATA);
       }

       return 0;
   }
c 复制代码
#include "head.h"

#define DATA  0   // 用于表示信号量元素的下标
#define SPACE 1

/* 函数功能:初始化一个信号量元素
 * 参数1:   信号量的ID
 * 参数2:   当前信号量元素的下标
 * 参数3:   在这块我们使用SETVAL,表示给信号量元素设置初值
 * 参数4:   给信号量元素设置的具体值
 */
void init_sem(int id, int num, int val)
{
    semctl(id, num, SETVAL, val);
}

/* 函数功能:通过信号量元素的设备,执行P操作
 * 参数1:   信号量的ID
 * 参数2:   当前信号量元素的下标
 */
void sem_p(int id, int num)
{
    struct sembuf buf[1];
    buf[0].sem_num = num;  // 信号量元素的下标
    buf[0].sem_op = -1;    // 执行P操作
    buf[0].sem_flg = 0;    // 通常不使用

    // 执行P操作
    semop(id, buf, 1); // 1 代表数组中元素的个数
}

/* 函数功能:通过信号量元素的设备,执行V操作
 * 参数1:   信号量的ID
 * 参数2:   当前信号量元素的下标
 */
void sem_v(int id, int num)
{
    struct sembuf buf[1];
    buf[0].sem_num = num;  // 信号量元素的下标
    buf[0].sem_op =  1;    // 执行V操作
    buf[0].sem_flg = 0;    // 通常不使用

    // 执行V操作
    semop(id, buf, 1); // 1 代表数组中元素的个数
}

int main(int argc,char *argv[])
{
/************************* 共享内存操作 **********************/

    // 1、获取键值,提供给共享内存使用
    key_t key = ftok(".", 3);

    // 2、获取共享内存ID
    int shmid = shmget(key, 1024, IPC_CREAT | 0644);

    // 3、实现内存映射
    char* ptr = shmat(shmid, NULL, 0);

/************************* 信号量操作 **********************/
    
    // 4、获取键值,提供给信号量使用
    key_t sem_key = ftok(".", 4);

    // 5、获取信号量的ID
    //    第二个参数用于表示信号量元素的个数
    int semid = semget(key, 2, IPC_CREAT | 0644);

    // 6、初始化两个信号量元素
    init_sem(semid, DATA,  0); // 初始化无数据
    init_sem(semid, SPACE, 1); // 初始化有资源

    // 下面这段代码只使用了共享内存中的一个字节
    while(1)
    {
        // 7、执行P操作,申请数据(想要进行读操作),数据减少
        sem_p(semid, DATA);

        printf("%c", *ptr);
        
        // 9、资源增加,数据减少
        sem_v(semid, SPACE);
    }

    return 0;
}
复制代码
   #include "head.h"

   int main(int argc,char *argv[])
   {
   /************************* 共享内存操作 **********************/

       // 1、获取键值,提供给共享内存使用
       key_t key = ftok(".", 3);

       // 2、获取共享内存ID
       int shmid = shmget(key, 1024, IPC_CREAT | 0644);

       // 3、实现内存映射
       char* ptr = shmat(shmid, NULL, 0);

   /************************* 信号量操作 **********************/
       
       // 4、创建POSIX信号 /space
       sem_t* space = sem_open("/space", O_EXCL);
       if (space == SEM_FAILED)
       {
           space = sem_open("/space", O_CREAT, 0644, 1);
       }

       // 4、创建POSIX信号 /data
       sem_t* data = sem_open("/data", O_EXCL);
       if (data == SEM_FAILED)
       {
           data = sem_open("/data", O_CREAT, 0644, 0);
       }

       // 5、给共享内存写入数据
       char buf[] = "0123456789";

       // 下面这段代码只使用了共享内存中的一个字节
       // 注意目的是为了验证共享内存在没有信号量等机制保证时,内存数据会出现践踏。
       int i = 0;
       while(1)
       {
           // 6、申请资源,无资源时阻塞等待
           sem_wait(space); // while(SPACE == 0);

           // 7、向共享内存中写入数据
           *ptr = buf[i++];
           if (i == 10)
           {
               i = 0;
           }

           // 8、投递数据
           sem_post(data);
       }

       return 0;
   }
c 复制代码
#include "head.h"

int main(int argc,char *argv[])
{
/************************* 共享内存操作 **********************/

    // 1、获取键值,提供给共享内存使用
    key_t key = ftok(".", 3);

    // 2、获取共享内存ID
    int shmid = shmget(key, 1024, IPC_CREAT | 0644);

    // 3、实现内存映射
    char* ptr = shmat(shmid, NULL, 0);

/************************* 信号量操作 **********************/
    
    // 4、创建POSIX信号 /space
    sem_t* space = sem_open("/space", O_EXCL);
    if (space == SEM_FAILED)
    {
        space = sem_open("/space", O_CREAT, 0644, 1);
    }

    // 4、创建POSIX信号 /data
    sem_t* data = sem_open("/data", O_EXCL);
    if (data == SEM_FAILED)
    {
        data = sem_open("/data", O_CREAT, 0644, 0);
    }

    while(1)
    {
        // 5、申请数据,无数据时阻塞等待
        sem_wait(data); // while(DATA == 0);

        // 6、从共享内存中读取数据
        printf("%c", *ptr);

        // 7、投递资源
        sem_post(space);
    }

    return 0;
}
相关推荐
wuyk55521 分钟前
【Socket 进阶之路】第 3 章 TCP 三次握手 & 四次挥手深度剖析|连接建立、断开、状态机、TIME_WAIT 核心工程问题
服务器·开发语言·网络·物联网·网络协议·tcp/ip
allnlei28 分钟前
s6-overlay - 装在 Docker 容器里的轻量级管家
java·docker·容器
IT_Octopus6 小时前
IntelliJ 本地日志路径自定义:`-DLOG_PATH=./logs` 为什么总“不听话“
java·log4j·intellij-idea
平头哥AI6 小时前
Day 22 _ 包装错误别丢链_%w、errors.Is 与 errors.As
android·服务器·学习·golang·go
长征coder7 小时前
【无标题】
java·性能优化
CharlesYu017 小时前
前端性能优化的第一性原理,是不断缩短“用户发起意图 → 获得可用结果”之间的时间
前端
新时代牛马7 小时前
PCI与PCIe 硬件原理、配置空间/BAR 与 Linux 驱动完整篇:从 LTSSM、TLP 到 ECAM 与probe
java·linux·服务器
Bs_MoneyMagnet8 小时前
基于springboot+vue的医疗健康便民服务平台的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring
平头哥技术团队8 小时前
Day 21 _ 页内锚点_给每段起个 id,目录写 href=_#id_,点一下页面就滚到那一段
前端·html·html5
sunshine22 girl8 小时前
Java学习一 环境配置2 Idea的入门使用和maven配置,项目启动脚本配置
java·maven