第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;
}
相关推荐
英俊潇洒美少年1 小时前
vue confirm、messageBox等弹窗关闭后焦点残留问题
前端·javascript·vue.js
九皇叔叔2 小时前
【04】SpringBoot3 MybatisPlus 查询(Mapper)
java·mybatis·mybatis plus
人道领域2 小时前
javaWeb从入门到进阶(SpringBoot基础案例)
java·开发语言·spring
harrain2 小时前
vue3怎么扩展第三方依赖库内部逻辑(拿element plus举例)
前端·javascript·vue.js·elementui
u0104058362 小时前
利用Java CompletableFuture优化企业微信批量消息发送的异步编排
java·开发语言·企业微信
j_xxx404_2 小时前
Linux:进程
linux·运维·服务器
yangminlei2 小时前
SpringSecurity核心源码剖析+jwt+OAuth(一):SpringSecurity的初次邂逅(概念、认证、授权)
java·开发语言·python
小张快跑。2 小时前
【SpringBoot进阶指南(一)】SpringBoot整合MyBatis实战、Bean管理、自动配置原理、自定义starter
java·开发语言·spring boot
A懿轩A2 小时前
【2026 最新】Java 与 IntelliJ IDEA 详细下载安装教程 带图演示(Windows 版)
java·windows·intellij-idea