进程间通信-system-v

进程间通信 ——System V IPC 讲解 消息队列是复杂进程间通信场景的理想选择,尤其适合需要结构化数据、异步处理和消息分类的场景。使用时需注意系统资源管理和权限控制,避免成为性能瓶颈或安全漏洞。 阅读详情

System V IPC概述

  • System V引入了三种高级进程间通信机制
  1. 消息队列、共享内存和信号量
  • IPC对象(消息队列、共享内存和信号量)存在于内核而不是文件系统中,由用户控制释放(用户管理IPC对象的生命周期),不像管道的释放由内核控制。

  • IPC对象通过其标识来引用和访问,所有的IPC对象在内核空间中唯一性标识ID,在用户空间中的唯一性标识称为Key.

  • IPC对象是全局对象,可以通过ipcs,ipcrm等命令来查看或删除

  • 每个IPC对象都由get函数创建

  1. msgget,shmget,semget,调用get函数时必须指定关键字key
andrew@andrew-Thurley:/work/linux-sys$ ipcs

--------- 消息队列 -----------
键        msqid      拥有者  权限     已用字节数 消息      

------------ 共享内存段 --------------
键        shmid      拥有者  权限     字节     连接数  状态      
0x00000000 884736     andrew     600        16777216   2                       
0x00000000 786433     andrew     600        524288     2          目标       
0x00000000 983042     andrew     600        524288     2          目标       
0x00000000 655363     andrew     600        524288     2          目标       
0x00000000 1933316    andrew     700        30072      2          目标       
0x00000000 1081349    andrew     600        524288     2          目标       
0x00000000 1409030    andrew     600        524288     2          目标       
0x00000000 1572871    andrew     600        524288     2          目标       
0x00000000 1835016    andrew     600        524288     2          目标       
0x51010013 1638409    andrew     600        1          1                       
0x00000000 1736714    andrew     600        268435456  2          目标       
0x00000000 2031627    andrew     600        524288     2          目标       
0x00000000 2064396    andrew     600        524288     2          目标       
0x00000000 2162701    andrew     600        524288     2          目标       
0x00000000 2195470    andrew     600        4194304    2          目标       
0x00000000 2326544    andrew     600        524288     2          目标       
0x00000000 2424849    andrew     600        524288     2          目标       
0x00000000 2555922    andrew     600        2097152    2          目标       
0x00000000 2850835    andrew     700        222828     2          目标       

--------- 信号量数组 -----------
键        semid      拥有者  权限     nsems     
0x51010012 32768      andrew     600        1 

消息队列

  • 消息队列是内核中的一个链表

  • 用户进程将数据传输到内核后,内核重新添加一些如用户ID,组ID,读写进程的ID和优先级等相关信息后并打成一个数据包称为消息

  • 允许一个进程或者多个进程往消息队列中写消息和读消息,但一个消息只能被一个进程读取,读取完毕后就自动删除

  • 消息队列具有一定的FIFO的特性,消息可以按照顺序发送到队列中,也可以几种不同的方式从队列中读取,每一个消息对垒在内核中用一个唯一的IPC标识ID表示

  • 消息队列的实现包括创建和打开队列、发送消息、读取消息和控制消息队列四中操作

创建或打开消息队列

#include <sys/msg.h>
int msgget(key_t key, int flag);
返回:成功返回内核中消息队列的标识ID,出错返回-1

消息控制

#include <sys/msg.h>
int msgctl(int msgid, intcmd, struct msqid_ds *buf);;
返回:成功返回0,出错返回-1

发送消息

#include <sys/msg.h>
int msgsnd(int msgqid, const void *ptr, size_t nbytes,int flag);
返回:成功返回0,出错返回-1
ptr:
struct mymesg{
    long mytype;
    char mtext[512];
}
  • nbytes 指定消息的大小,不包括mtype的大小
  • mtype指消息的类型,它由一个整数来代表,并且它只能是大于0的整数
  • mtext是消息数据本身
  • 在linux中,消息的最大长度是4056个字节,其中包括mtype,它占有4个字节
  • 结构体mymesg用户可自定义,但第一个成员必须是mytype

接收消息

#include <sys/msg.h>
ssize_t msgrcv(int msgqid, void *ptr,size_t nbytes,long type, int flag);
返回:成功返回消息的数据部分长度,出错返回-1
    type : 消息类型
    type == 0 : l获得消息队列中的第一个消息
    type > 0 : 获得消息队列中类型为type的第一个消息
    type < 0 : 获得消息中小于或等于type和绝对值的消息`

发送消息示例:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>

typedef struct{
    long type; //消息类型
    int start; //消息数据本身
    int end;
}MSG;


/**
 *  往消息队列中发送消息
 */

int main(int argc, char *argv[])
{
    if(argc < 2){
        printf("usage: %s key \n", argv[0]);
        exit(1);
    }

    key_t key = atoi(argv[1]);
    printf("key: %d\n", key);
    //创建消息队列
    int msq_id;
    if((msq_id = msgget(key, IPC_CREAT | IPC_EXCL | 0777)) < 0)
    {
        perror("msgget error");
    }
    printf("msg id: %d\n", msq_id);


    //定义要发送的消息
    MSG m1 = {4, 4, 400};
    MSG m2 = {2, 2, 200};
    MSG m3 = {1, 1, 100};
    MSG m4 = {6, 6, 600};
    MSG m5 = {6, 60, 6000};


    //发型消息到消息队列
    if(msgsnd(msq_id, &m1, sizeof(MSG) - sizeof(long), IPC_NOWAIT) < 0){
        perror("msgsnd error");
    }

    if(msgsnd(msq_id, &m2, sizeof(MSG) - sizeof(long), IPC_NOWAIT) < 0){
        perror("msgsnd error");
    }

    if(msgsnd(msq_id, &m3, sizeof(MSG) - sizeof(long), IPC_NOWAIT) < 0){
        perror("msgsnd error");
    }

    if(msgsnd(msq_id, &m4, sizeof(MSG) - sizeof(long), IPC_NOWAIT) < 0){
        perror("msgsnd error");
    }

    if(msgsnd(msq_id, &m5, sizeof(MSG) - sizeof(long), IPC_NOWAIT) < 0){
        perror("msgsnd error");
    }

    //获取发送消息的总数
    struct msqid_ds ds;
    if(msgctl(msq_id, IPC_STAT, &ds) < 0){
        perror("msgctl error");
    }

    printf("msg total : %ld\n", ds.msg_qnum);

    exit(0);
}

执行结果

andrew@andrew-Thurley:/work/linux-sys/TEK$ ./a.out 32
key: 32
msg id: 0
msg total : 5
andrew@andrew-Thurley:/work/linux-sys/TEK$ ipcs -q

--------- 消息队列 -----------
键        msqid      拥有者  权限     已用字节数 消息      
0x00000020 0          andrew     777        40           5           

# 同样的key值发送之后只能发送一次,等待接受之后才能再发送
andrew@andrew-Thurley:/work/linux-sys/TEK$ ./a.out 32
key: 32
msgget error: File exists
msg id: -1
msgsnd error: Invalid argument
msgsnd error: Invalid argument
msgsnd error: Invalid argument
msgsnd error: Invalid argument
msgsnd error: Invalid argument
msgctl error: Invalid argument
msg total : 0
andrew@andrew-Thurley:/work/linux-sys/TEK$ ./a.out 36
key: 36
msg id: 32769
msg total : 5
andrew@andrew-Thurley:/work/linux-sys/TEK$ ipcs -q

--------- 消息队列 -----------
键        msqid      拥有者  权限     已用字节数 消息      
0x00000020 0          andrew     777        40           5           
0x00000024 32769      andrew     777        40           5           

# 删除消息队列
andrew@andrew-Thurley:/work/linux-sys/TEK$ ipcs -q 

--------- 消息队列 -----------
键        msqid      拥有者  权限     已用字节数 消息      
0x00000024 32769      andrew     777        40           5           

andrew@andrew-Thurley:/work/linux-sys/TEK$ ipcrm -q 32769
andrew@andrew-Thurley:/work/linux-sys/TEK$ ipcs -q 

--------- 消息队列 -----------
键        msqid      拥有者  权限     已用字节数 消息 
  • 说明:消息队列中的消息被接收完之后消息队列还是存在的,由用户删除

共享内存

  • 共享内存区域是被多个进程共享的一部分物理内存。

  • 多个进程都可以把该共享内存映射到自己的虚拟内存空间,所有用户空间的进程若要操作共享内存,都要将其映射到自己的虚拟内存空间中,通过映射的虚拟内存空间地址去操作共享内存,从而达到进程间的数据通信。

  • 共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入数据,共享内存中的所有进程就可以立刻看到其中的内容

  • 本身不提供同步机制,可以通过信号量进行同步

  • 提升数据处理效率,一种效率最高的IPC机制

  • shmget创建共享内存函数

  • shmat函数映射共享内存,将这段创建共享的共享内存映射到具体的进程虚拟内存空间

创建共享内存

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

int shmget(key_t key, size_t size, int shmflg);

共享内存控制

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

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

共享内存映射和解除映射

#include <sys/types.h>
#include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg);
返回: 成功返回共享内存映射到进程虚拟内存空间中的地址,失败返回-1
int shmdt(const void *shmaddr);
返回: 如果失敗,則返回-1  
  • 父子进程通过管道创建共享内存案例

共享内存使用示例:

telll.c

//< 使用管道进行同步共享内存的创建
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "tell.h"

//< 管道文件描述符数组
static int fd[2];

//管道初始化
void init()
{
    if(pipe(fd) < 0){
        perror("perror");
    }

}

//利用管道进行等待
void wait_pipe()
{
    char c;
    //管道读写默认是阻塞性的
    if(read(fd[0], &c, 1) < 0){
        perror("wait pipe error");
    }

}

//利用管道进行通知
void notify_pipe()
{
    char c ='c';
    if(write(fd[1], &c, 1) != 1){
        perror("notify pipe error");
    }

}

//销毁管道
void destroy_pipe()
{
    close(fd[0]);
    close(fd[1]);

}

tell.h

#ifndef __TELL_H__
#define __TELL_H__

//管道初始化
extern void init();

//利用管道进行等待
extern void wait_pipe();
//利用管道进行通知
extern void notify_pipe();
//销毁管道
extern void destroy_pipe();

#endif //TELL

cal_shm.c

//< 使用管道进行同步共享内存的创建
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include "tell.h"

int main(int argc, char *argv[])
{
    //创建共享内存
    int shmid;
    if((shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | IPC_EXCL | 0777)) < 0){
        perror("shmget error");
        exit(1);
    }
    pid_t pid;
    init(); //初始化管道
    if((pid = fork()) < 0){
        perror("fork error !");
        exit(1);
    }
    else if(pid > 0){
        //进行共享内存映射
        int *pi;
        pi = (int *)shmat(shmid, 0, 0);
        if(pi == (int *)-1){//<因为pi是指针类型的数据
            perror("shmat error");
            exit(1);  
         }
         //往共享内存中写入数据(通过操作映射的地址即可)
        *pi = 100;
        *(pi +1) =200;
        //操作完,解除共享内存映射
        shmdt(pi);
        //< 通知子进程读取数据
        notify_pipe();
        destroy_pipe();
        wait(0);
    }else{// child process
        //< 子进程阻塞,等待父进程往共享内存中写入数据
        wait_pipe();
        //子进程从共享内存中读取数据
        //子进程进行共享内存的映射
        int *pi = (int *)shmat(shmid, 0, 0);
        if(pi == (int *)-1){
            perror("shmat error");
            exit(1);
        }
        printf("start : %d end : %d \n", *pi, *(pi+1));
        //< 读取完数据,解除映射 
        shmdt(pi);
        //< 删除共享内存 共享内存只有一个,在子进程和父进程中只有一个
        shmctl(shmid, IPC_RMID, NULL);

        destroy_pipe();

    }

    exit(0);
}


Makefile


all:cal_shm

cal_shm: cal_shm.c tell.c
	gcc -o cal_shm -I. tell.c cal_shm.c

信号量

进程间信号量

  • 进程信号量本质上就是共享资源的数目,用来控制对共享资源的访问
  • 用于进程间资源的互斥和同步
  • 每种共享资源对应一个信号量,为了便于大量共享资源的操作引入了信号量集,可对所有的信号量一次性操作。对信号量集中的所有操作可以要求全部陈宫,也可以部分成功。
  • 二元信号量(信号灯)值为和
  • 对信号量做PV操作

创建信号量集

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semget(key_t key, int nsems, int semflg);

返回:成功返回信号量集ID, 出错返回-1
  • key:用户指定的信号量集键值
  • nsems:信号量集中信号量个数
  • flag:IPC_CREAT、IPC_EXECL等权限的组合

信号量集控制

       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/sem.h>

       int semctl(int semid, int semnum, int cmd, ...);

DESCRIPTION
       semctl()  performs the control operation specified by cmd on the System V sema‐
       phore set identified by semid, or on the semnum-th semaphore of that set.  (The
       semaphores in a set are numbered starting at 0.)

       This  function  has  three or four arguments, depending on cmd.  When there are
       four, the fourth has the type union semun.  The  calling  program  must  define
       this union as follows:

           union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };

       The semid_ds data structure is defined in <sys/sem.h> as follows:

           struct semid_ds {
               struct ipc_perm sem_perm;  /* Ownership and permissions */
               time_t          sem_otime; /* Last semop time */
               time_t          sem_ctime; /* Last change time */
               unsigned long   sem_nsems; /* No. of semaphores in set */
           };

       The  ipc_perm  structure is defined as follows (the highlighted fields are set‐
       table using IPC_SET):

           struct ipc_perm {
               key_t          __key; /* Key supplied to semget(2) */
               uid_t          uid;   /* Effective UID of owner */
               gid_t          gid;   /* Effective GID of owner */
               uid_t          cuid;  /* Effective UID of creator */
               gid_t          cgid;  /* Effective GID of creator */
               unsigned short mode;  /* Permissions */
               unsigned short __seq; /* Sequence number */
           };
  • semid:信号量集ID
  • semnum: 0表欧式所有信号量操作,信号量编号从开始。
  • val:防止获取或设置信号量集中某个信号量值
  • buf:信号量集属性指针
  • array:放置获取或设置信号量集中所有信号量的值

信号量集操作

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semop(int semid, struct sembuf *sops, size_t nsops);

int semtimedop(int semid, struct sembuf *sops, size_t nsops,
               const struct timespec *timeout);

信号量模块封装示例:

pv.c

//< 信号量操作PV原语
#include <sys/sem.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <assert.h>

union semun{
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

//< 初始化semnums个信号灯/信号量的值(value)
int I(int semnums, int value)
{
    //创建信号量集
    int semid = semget(IPC_PRIVATE, semnums, IPC_CREAT | IPC_EXCL | 0777);
    if(semid < 0){
        perror("semget faild!");
        return -1;
    }
    union semun un;
    unsigned short *array = 
            (unsigned short *)calloc(semnums, sizeof(unsigned short));

    int i;
    for(i = 0; i < semnums; i ++)
    {
        array[i] = value;
    }
    un.array = array;
    /*
     * 初始化信号集中所有的信号灯的初值0;
     * 0:标示要初始化的所有信号集
    */   
   if (semctl(semid, 0, SETALL, un) < 0){
       perror("semctl error");
       return -1;
   }
   free(array);
   return semid; 
}

//< 对信号量集(semid)中的信号灯(semnum)做P(value)操作
void P(int semid, int semnum, int value)
{
    assert(value >= 0);
    //定义sembuf类型的结构体数组,防止若干个新结构体变量 , ops中有多少个信号量决定
    //防止要操作的信号量、P或V操作
     struct sembuf ops[] = 
                        {{semnum, -value, SEM_UNDO}};
    if(semop(semid, ops, sizeof(ops)/sizeof(struct sembuf)) < 0){
        perror("semop error");
    }

}

//< 对信号量集(semid)中的信号灯(semnum)作V(value)操作
void V(int semid, int semnum, int value)
{     
     assert(value >= 0);
    //定义sembuf类型的结构体数组,防止若干个新结构体变量 , ops中有多少个信号量决定
    //防止要操作的信号量、P或V操作
     struct sembuf ops[] = 
                        {{semnum, -value, SEM_UNDO}};
    if(semop(semid, ops, sizeof(ops)/sizeof(struct sembuf)) < 0){
        perror("semop error");
    }    

}

//< 销毁信号量集
void D(int semid)
{
    if(semctl(semid, 0, IPC_RMID, NULL) < 0){
        perror("semctl error");
    }

}

pv.h

//< 信号量操作PV原语
#ifndef __PV_H__
#define __PV_H__

//< 初始化semnums个信号灯/信号量的值(value)
extern int I(int semnums, int value);

//< 对信号量集(semid)中的信号灯(semnum)做P(value)操作
extern void P(int semid, int semnum, int value);

//< 对信号量集(semid)中的信号灯(semnum)作V(value)操作
extern void V(int semid, int semnum, int value);

//< 销毁信号量集
extern void D(int semid);


#endif //PV_H

[Linux系统编程]进程间通信—system V System V IPC 资源的生命周期:在使用 System V IPC(包括信号量、消息队列、共享内存等) 时,需要特别注意这些资源的生命周期问题。IPC 资源必须显式删除:System V IPC 资源(如共享内存段、信号量集、消息队列等)不会在进程结束时自动清除。你必须使用 shmctl()、semctl() 或 msgctl() 等系统调用来手动删除 IPC 资源,否则这些资源会一直存在于系统中,直到系统重启。 阅读详情

相关推荐

Fluent新手避坑:遇到‘Floating point exception’别慌,这7个排查步骤帮你搞定

本文为Fluent新手提供了7个排查'Floating point exception'错误的实用步骤,包括边界条件检查、时间步长优化、求解器配置等关键技巧。通过系统化的诊断流程,帮助用户快速定位并解决CFD仿真中的浮点异常问题,提升计算稳定性。

weixin_42531886的博客 285

进程间通信之System V消息队列

struct ipc_perm:这是System V版本系列进程间通信所用到的一个公共版结构体。也就是Linux内核为每个IPC对象维护一个数据结构。 第一字段,这个属性非常重要,它称之为ipckey。 进程间通信的方式其实本质上它们都得在内核中申请一定的资源,而ipckey其实就是在描述着内存中惟一 一个消息队列/一块共享内存/一个信号量集这样的资源,因为一个操作系统可以创建很多个消息队列。 S...

chirrupy_hamal的博客 525

数仓 - 促销敏感度、评论敏感度

1. 促销敏感度 步骤1. 首先按照最后一次下单时间及有无复购情况将用户分为四大群体: 近一年有购物行为且复购的用户 -- L1 (今年复购用户) 近一年有购物行为但无复购的用户 --L2 (今年一单购用户) 最后一次下单时间在1年之前且有复购的用户 --L3 (今年无购且只有一单用户) 最后一次下单时间在1年之前但无复购的用户 -- L4 (今年无购多单用户) 步骤2. 每一类用户群再根据优惠订单占比、每单优惠金额占比的平均值、优惠金额这三个指标进行k-means聚类,分为: 非常敏感 -

weixin_41332009的博客 1898

进程间通信------消息队列

消息队列        消息队列是进程间通信的另一种方式。一个进程通过系统调用接口创建一个消息队列。操作系统会在内核中开辟一片内存用于进程间通信。而这片内存现在又以消息队列的形式来进行通信的。        消息队列提供了一个进程向另一个进程发送数据块的方法来进行通信。每个数据块都有一个类型,接收进程根据类型来接受自己想要的数据块,且消息的读取不一定是先入先出的,它是由类型决定的。        ...

sandmm112的博客 553

Log4Shell漏洞复现:从原理到实战的完整指南

日志记录是软件开发中用于追踪应用状态和排查问题的关键技术。然而,当日志组件对用户输入进行不当解析时,可能引发严重的安全风险。Log4j2作为Java生态中广泛使用的日志框架,其Lookup功能允许在日志中动态插入变量,这一设计初衷虽为便利,却因递归解析机制埋下了隐患。攻击者通过构造特定的JNDI(Java命名和目录接口)查询字符串,可诱使应用加载并执行远程恶意代码,从而实现远程命令执行。这种漏洞的价值在于其极低的利用门槛和极高的潜在危害,常被用于渗透测试和安全评估中,以验证系统的防御能力。本文以CVE-20

weixin_30496999的博客 275

手把手教你用ZEMAX复现贝塞尔光束:从Thorlabs锥透镜到Edmund透镜的完整光路搭建

本文详细介绍了如何在ZEMAX光学设计软件中复现贝塞尔光束,从Thorlabs锥透镜到Edmund透镜的完整光路搭建过程。通过逐步指导,帮助研究人员和工程师掌握光学设计技巧,实现无衍射特性的贝塞尔光束生成,适用于激光加工和生物成像等领域。

weixin_33737774的博客 176

【Linux学习】进程间通信——system V(共享内存 | 消息队列 | 信号量)

详细介绍了共享内存的通信方式,包括它的原理和实现,以及涉及到的细节。大致描述了消息队列和信号量的一些概念。

weixin_63726869的博客 2554

DSP篇--C6678功能调试系列之EDMA3调试

EDMA主要用于数据的搬运,发送、接收,其搬运数据的形式有;AB模式,ABC模式以及ping-pong模式。 EDMA3分初始化、参数配置、以及中断配置。其中中断配置则需要注意的内容主要有:挂载的TC通道,对应的触发事件,以及中断的使能。

nanke_yh的博客 1720

system V——进程间通信

假简单介绍了system V进程间通信的内容

weixin_74074953的博客 1193

某Z节验证码

某Z节验证码、captchaBody、滑块、旋转、空间推理

mamenqi_csdn的博客 770

目标检测YOLO实战应用案例100讲-跨模态、多级别融合的RGB-D显著目标检测方法研究(续)

在第二章介绍了本研究的跨模态特征融合方法,第二章对于多级别特征的融合, 使用的是与基线模型baseline相同的方法:相邻级别的特征中,高级特征进行上采 样到与低级特征相同的尺度,再将高级特征通过降维得到与低级特征相同的通道数 量,最后对二者进行特征叠加,如此自顶向下的进行多级别的特征融合。本章主要 介绍本研究在特征层面的另一发现,并基于此发现引出的本文的第二个创新点:多 级别特征的融合方法。另外,在网络最深层,本文设计了一个新的模块来获取大的 感受野,对于大尺度目标能够增加更多语义信息,提升检测效果。 骨

qq_36130719的博客 466

【Linux】进程间通信——System V共享内存

本篇文章围绕Linux中的System V共享内存展开讲解,包含其概念和原理、API介绍与使用方式和通信的实现等内容

Eristic0618的博客 1312

《AI 时代FPGA的全栈开发实战・从入门到精通》专栏启动说明

《智驱FPGA》专栏面向初学者,聚焦AI时代FPGA开发新范式,以ChatGPT、ICCoder2.0等工具全程辅助,覆盖纯逻辑、Zynq软硬协同、端侧AI加速、高速接口等核心方向。通过126节图文+14个实战项目,传授AI生成代码、Prompt工程、时序优化等能力,助力学员从零成长为具备工程竞争力的FPGA工程师,结业可独立完成完整项目并写入简历。

现任某外企的算法工程师!专注于人工智能、嵌入式、FPGA、论文写作四大主题的教程和经验分享!辅导请➕v :sci666888999 172

使用管道和system V进行进程间通信

然后分别在父子进程中关闭关闭其不需要的操作文件方式,此时关闭并不会直接将文件给关闭,因为我们文件的指向是采用引用计数的方式的,所以关闭进程的文件,只会使引用计数--,只有减到0才会真正的关闭文件。我们首先创建管道(实质就是打开同一个文件两次,形成两个文件描述符),然后再fork创建子进程,那么子进程会拷贝文件描述符表中的内容,此时,父子进程文件描述符表中的文件指针所指向的就是同一个文件,继续fork继续拷贝...但是我们发现,我们的结果是按照顺序读写的,也就是子进程写完一份内容,父进程才会读取一份内容。

C_Rio的博客 1022

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

进程间通信—system v标准

System v标准的进程间通信包括共享内存,消息队列和信号量。我们着重介绍共享内存。前面我们介绍了通信的前提是:不同进程能看到同一份内存资源。前面我们介绍的管道是借助了文件系统来让不同进程看到同一份资源,我们即将介绍的共享内存是依靠在内存中创建一个共享内存区实现。

klausur31的博客 787

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Linux系统入门:System V进程间通信

System V标准的三种资源 -- 共享内存、消息队列、信号量的认识

小苹果今天也拜托你了 1017

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Linux 进程间通信——System V

本文介绍了SystemV进程间通信中的共享内存机制。共享内存通过将物理内存区域映射到多个进程的地址空间实现高效通信,其生命周期随内核而非进程。文章详细讲解了共享内存的关键系统调用接口:shmget(创建)、shmat(挂载)、shmdt(卸载)和shmctl(控制管理),并给出了C++封装示例。通过管道文件实现同步机制,解决共享内存无内置同步的缺点。最后指出共享内存大小需为4KB整数倍,并介绍了内核管理结构shmid_ds。共享内存是最高效的IPC方式,但需要配合同步机制保证数据一致性。

2301_79976271的博客 953

【Linux】进程间通信——System V消息队列和信号量

本篇文章围绕Linux中的System V消息队列和信号量展开讲解,包含其概念和原理、API介绍与使用方式等内容

Eristic0618的博客 1895

【Linux系统编程】System V进程间通信---共享内存与System V内核数据结构

System V是人为规定出的用于操作系统本地进程间通信的一套标准,而System V中的进程间通信方式主要分为3种1、共享内存2、消息队列3、信号量其中,共享内存这篇博文会详细介绍。

m0_73904148的博客 1302

【Linux】进程间通信——system V(共享内存 | 消息队列 | 信号量)

同一主机内的进程间通信方案,在OS层面专门为进程间通信设计的方案让不同的进程看到同一份资源system V标准下的三种通信方式共享内存消息队列信号量我们来看看 system V标准下的三种通信方式。⭐主体学习【Linux学习】进程间通信——system V(共享内存 | 消息队列 | 信号量)咱们按照下面的图解:​。

AAlykk的博客 1398

System V IPC(进程间通信)机制详解

在共享内存模型中,进程A和进程B都可以直接访问同一块物理内存区域(即“共享区”)。这意味着数据不需要通过系统调用或其他中间层进行复制或传输,从而减少了数据传输的开销。共享内存通过允许进程直接访问同一块物理内存区域,减少了数据传输和I/O操作的开销,降低了延迟,从而提高了进程间通信的效率。当A进程需要与B进程通信时,只需要把共享区的虚拟地址与物理地址的映射写入两进程的页表中。因此,进程A可以对该物理地址直接进行写入;而B进程则是通过页表的映射关系,从该物理地址直接进行读取。

无敌岩雀的博客 2498

Linux进程间通信——system V消息队列

System V消息队列是一种进程间通信机制,通过让不同进程访问同一消息队列实现数据交换。内核维护由msqid_ds结构描述的消息队列,通过"先描述再组织"方式管理。通信时进程发送带有类型标识的数据块(包含mtype和mtext)。关键接口包括:msgget获取队列标识符,msgctl进行控制操作,msgsnd发送消息,msgrcv接收消息。消息队列与共享内存、信号量同属System V标准,具有相似的管理结构。发送消息时需要指定数据类型,接收时可根据类型筛选消息。这种机制适用于需要按消

2301_79705195的博客 972

进程间通信III·System V 系列(linux)

摘要:System V共享内存是跨Unix系统的进程间通信方案,通过在物理内存开辟共享块并映射到进程虚拟地址空间实现高效通信。关键操作包括:shmget创建(需指定大小和唯一key)、shmat挂接、shmdt分离和shmctl控制。其特点是:1)直接内存访问无系统调用;2)生命周期随内核;3)需创建/获取端配合使用;4)速度最快但需自行处理同步。文中还提供了C++实现示例,展示服务器/客户端通过共享内存传递字符数据的过程。注意共享内存默认按4KB对齐分配,可通过ipcs/ipcrm命令管理。

2401_86702190的博客 1160

基于system V共享内存的进程间通信

摘要:本文介绍了SystemV共享内存这一高效的进程间通信(IPC)机制。共享内存允许不同进程直接访问同一物理内存,避免了内核数据拷贝,是速度最快的IPC形式。文章详细讲解了共享内存的关键操作:shmget创建/获取共享内存、shmat附加到进程地址空间、shmdt分离共享内存以及shmctl控制共享内存。通过示例代码展示了服务端创建共享内存、客户端获取并访问共享内存的完整通信流程。共享内存虽高效但缺乏同步机制,需要额外措施保证数据一致性。该机制特别适合需要高性能数据交换的场景。

2401_82551617的博客 772
上一篇: pycharm 常用快捷键
下一篇: Io多路复用
andrewbytecoder
andrewbytecoder 领域专家: C/C++技术领域 领域专家: C/C++技术领域
博客等级 码龄10年 3476粉丝 687原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

andrewbytecoder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值