IPC 进程间通信 interprocess communicate

三大类:

1、古老的通信方式

无名管道 有名管道 信号

2、IPC对象通信 systemvBSD suse fedora kernel.org

消息队列(用的相对少,这里不讨论)

共享内存

信号量集

3、socket通信

网络通信

线程信号,posix sem_init

特列:古老的通信方式中信号是唯一的异步通信

所有的通信方式中共享内存是唯一的最高效

管道==》无名管道、有名管道

无名管道 ===》pipe ==》只能给有亲缘关系进程通信

有名管道===》fifo==》可以给任意单机进程通信

无名管道

1、管道是半双工的工作模式

2、所有的管道都是特殊的文件不支持定位操作。Iseek->>fd fseek->>FILE*

3、管道是特殊文件,读写使用文件IO。fgets,fread,fgetc,(这个有缓冲区)

open,read,write,close(首选)

1,读端存在,一直向管道中去写,超过64k,写会阻塞。

2.写端是存在的,读管道,如果管道为空的话,读会阻塞。

3.管道破裂,,读端关闭,写管道。

4.read0,写端关闭,如果管道没有内容,read;

使用框架:

创建管道==》读写管道==》关闭管道

1、无名管道===》管道的特例===>pipe函数

特性:

1.1亲缘关系进程使用

1.2 有固定的读写端

复制代码
流程:
创建并打开管道:pipe函数
#include <unistd.h>
int pipe(int pipefd[2]);
功能:创建并打开一个无名管道
参数:pipefd[0]==>无名管道的固定读端

读堵塞

cs 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc,char *argv[])
{
   int fd[2]={0};
   int ret = pipe(fd);
   if(-1==ret)
   {
    perror("pipe");
    return 1;
   }
   pid_t pid =fork();
   if(pid>0)
   {
    close(fd[0]);
    char buf[]="hello,child";
    sleep(3);
    write(fd[1], buf,sizeof(buf)+1);

   }else if(pid==0)
   {
    close(fd[1]);
    char buf[50]={0};
    read(fd[0], buf, sizeof(buf));
    printf("child,buf :%s\n",buf);
   }else
   {
    perror("fork");
    return 1;
   }



    return 0;
}

写堵塞:

cs 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


int main(int argc, char *argv[])
{
    int fd[2]={0};
    // create pipe + open pipe 
    int ret = pipe(fd);
    if(-1 == ret)
    {
    
        perror("pipe");
        return 1;
    }

    pid_t pid = fork();
    if(pid>0)
    {//write fd 
        close(fd[0]);
        char buf[1024]={0};
        memset(buf,'a',sizeof(buf));
        int i = 0 ;
        for(i=0;i<65;i++)
        {
            write(fd[1],buf,sizeof(buf));
            printf("i is %d\n",i);
        }
    }
    else if(0==pid)
    {// read only
        close(fd[1]);
        sleep(5);
        char buf[50]={0};
        read(fd[0],buf,sizeof(buf));
        printf("child ,buf:%s\n",buf);
    }
    else 
    {
        perror("fork");
        return 1;
    }
    return 0;
}

注意:管道的创建必须在fork之前

有名管道

有名管道===》fifo==》有文件名称的管道。 文件系统中可见

框架:

创建有名管道==》打开有名管道==》读写管道==》关闭管道==》卸载有名管道

有名管道的打开,会堵塞。

1.创建:mkfifo

cs 复制代码
#include <sys/types.h>
#include <sys/stat.h>
remove0;

int mkfifo(const char *pathname, mode_t mode);
功能:在指定的pathname路径+名称下创建一个权限为
      mode的有名管道文件。
参数:pathname要创建的有名管道路径+名称
     mode 8进制文件权限。
返回值:成功0
       失败-1;

2.打开有名管道 open

cs 复制代码
注意:该函数使用的时候要注意打开方式,
因为管道是半双工模式,所有打开方式直接决定
当前进程的读写方式。
一般只有如下方式:
int fd-read = open("./fifo",O_RDONLY); ==>fd 是固定读端
int fd-write = open("./fifo",O_WRONLY); ==>fd 是固定写端
不能是O_RDWR方式打开文件。
不能有O_CREAT选项,因为创建管道有指定的mkfifo函数

3、管道的读写:文件IO

cs 复制代码
读: read(fd-read,buff,sizeof(buff);
写 : write(fd-write,buff,sizeof(buff);

4、关闭管道:

close(fd)

5、卸载管道:remove()

cs 复制代码
int unlink(const char *pathname);
功能:将指定的pathname管道文件卸载,同时
从文件系统中删除。
参数:ptahtname 要卸载的有名管道
返回值:成功0
失败-1;

进程间通信===》信号通信

应用:异步通信(时间随机)。中断(被更高优先级的进程打断,等其工作完之后再回到本程序)。

1~64;32应用编程。

信号处理,忽略9和19.

共享内存

IPC对象操作通用框架:

Ox ftok

key值 ==>申请 ==》读写 ==》关闭 ==》卸载

key值:===》唯一键值

创建方式有三种:

1、IPC_PRIVATE固定的私有键值,其值等于 OxO,一般用于有亲缘关系的进程间使用。

2、ftok(创建临时键值。

复制代码
#include <sys/types.h>
#include <sys/ipc.h>
"/etc"!
key_t ftok(const char *pathname, int proj_id);
功能:通过该函数可以将pathname指定的路径用来以
proj_id生成唯一的临时键值。
参数:pathname 路径+名称===》任意文件,只要不会
被删除重建即可。
proj_id 整形的数字,一般用ASCll码的单字符
表示与参数1的运算。
返回值:成功返回唯一键值
失败-1;

ipcs :进程间通信命令显示

ipcrm:进程间通信的删除

eg:

写:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv)
{
  key_t key = ftok("./", '!');
  if (-1 == key)
  {
    perror("ftok");
    return 1;
  }
  printf("key is 0x%x\n", key);

  int shmid = shmget(key, 4096, IPC_CREAT | 0666);
  if (-1 == shmid)
  {
    perror("shmid");
    return 1;
  }

  void *p = shmat(shmid, NULL, !SHM_RDONLY);
  if ((void *)-1 == p)
  {
    perror("shmat");
    return 1;
  }
  char buf[] = "hello,this is shm test";
  // strcpy(p,buf);
  memcpy(p, buf, strlen(buf));
  shmdt(p);

  return 0;
}

读:

cs 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv)
{
  key_t key = ftok("./", '!');
  if (-1 == key)
  {
    perror("ftok");
    return 1;
  }
  printf("key is 0x%x\n", key);

  int shmid = shmget(key, 4096, IPC_CREAT | 0666);
  if (-1 == shmid)
  {
    perror("shmid");
    return 1;
  }

  void *p = shmat(shmid, NULL, !SHM_RDONLY);
  if ((void *)-1 == p)
  {
    perror("shmat");
    return 1;
  }
  char buf[4096] = {0};
  // strcpy(p,buf);
  memcpy(buf, p, sizeof(buf));
  printf("buf %s\n", buf);
  shmdt(p);
 // shmctl(shmid, IPC_RMID, NULL);
  return 0;
}
相关推荐
NiceCloud喜云12 分钟前
Anthropic 一周三连发:Cowork 多端、Fable 5 按需付费、J-space 论文的技术解读
java·服务器·网络·人工智能·ai
门思科技36 分钟前
TKL + EB:重新定义 LoRaWAN 在存量设备改造中的价值,让传统设备快速接入物联网
网络·物联网
qeen8742 分钟前
【Linux】指令补充与shell的简单介绍
linux·运维·服务器
hai3152475431 小时前
九章芯片电路集成体系:密度矩阵逆向·全域均衡网络计算总框架
网络·线性代数·矩阵
DLYSB_1 小时前
《从零开始搭建机房轻量化“声光告警”系统:基于 HTTP API 与 TTS 的运维实践》
运维·网络协议·http·报警灯
阿成学长_Cain1 小时前
Linux talk 命令详解:经典终端实时聊天工具,无需图形界面即可对话
linux·运维·前端
芝麻馅汤圆儿1 小时前
跨三层环境(交换机vlan/vlanif配置)
网络
wjql22 小时前
手机远程操控另一台手机的方法 手机可以远程操控手机吗
网络
一拳一个娘娘腔2 小时前
【后渗透-Linux篇】Linux 提权与逃逸:从 www-data到 root的蜕变
linux·运维·服务器
jieyucx2 小时前
零基础通关:Shell 编程核心语法全景详解
linux·运维·编程·shell