Linux 进程通信

article/2025/9/14 9:31:11

Linux 进程通信

1.传统进程通信

1.1 信号

信号机制是在软件层次上对中断机制的一种模拟。
信号的捕获与处理也成为系统的“软中断”机制。

1.1.1 常用信号

每个信号都有一个编号和宏定义的名称,这些名字都已SIG开头。宏定义在signal.h头文件中。

1.1.2 信号的处理

缺省操作,默认的信号处理方式。SIG_DFL
忽略信号,进程忽略接收到的信号,但SIGKILL和SIGSTOP不能忽略。SIG_DFL
捕获信号,提供一个信号处理函数,而不是使用默认的信号处理方式。要求内核此时切换到用户态。

CUP的两种状态:内核态和用户态
点击这里有详细介绍

1.1.3 信号处理函数
  1. signal() 定义进程收到信号后的处理方法
#include<signal.h>
void (*signal(int signum, void(*func)(int)))(int);

signum: 信号名称,整数值
func:一个指针,指向信号处理函数。该参数还可以是SIG_DFL或SIG_IGN(前者为默认的缺省操作的函数,后者为默认的忽略信号的函数)
调用成功,返回原来的信号处理函数的指针;失败则返回SIG_ERR

  1. kill() 向进程或进程组发送一个信号
#include<signal.h>
int kill(pid_t pid, int sig);

pid: 接收信号的进程ID。当pid为0时,发送给与当前进程同组的所有进程。
sig: 信号名称
信号发送成功返回0;信号发送失败返回-1。

1.2 管道

连接两个进程的连接器,数据在其中单向流动。

1.2.1 普通管道

位于内存中。只能用于有亲缘关系进程(父子进程)之间的单向通信。
当一个管道建立后,将获得两个文件描述符,分别用来对管道进程读取和写入。通常将其称为管代的写入端和管道的读取端。

这里的写入端和读取端指的是对管道的写入和读取。

pipe() 创建一个普通管道

#include<unistd.h>
int pipe(int filedes[2])

filedes[0]: 读端口的文件描述符
filedes[1]: 写端口的文件描述符
调用成功返回0;调用失败返回-1。

普通管道读写规则:
1. 读规则
关闭管道的写端: close (fd[1])
读出: read(fd[0], buf, size); 从管道读端口fd[0]读出size个字符放到buf中
读出后关闭管道的读端: close(fd[0])
2. 写规则
关闭管道的读端: close(fd[0])
写入: write(fd[1], buf, size); 把buf中的长度为size的字符送到管道写端口fd[1]
写入后关闭管道的写端: close (fd[1])

两个进程通过一个管道只能实现单向通信,如果需要父子进程双向通信,就必须另打开一个管道。
在管道满时,写管道操作将被阻塞;在管道空时,读管道操作将被阻塞。

例子:

/** 利用两个管道进行双向通信,实现父子进程协作把整数x1加到10*/
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#include<stdio.h>
int main()
{int x = 1;int pipe1[2], pipe2[2];pid_t val;pipe(pipe1);pipe(pipe2);if((val = fork()) <0 )exit(1);if(val == 0){close(pipe1[1]);close(pipe2[0]);while(x<=9){read(pipe1[0], &x, sizeof(int));printf("Child:%d, read:%d\n", getpid(), x++);write(pipe2[1], &x, sizeof(int));}close(pipe1[0]);close(pipe2[1]);}else{close(pipe2[1]);close(pipe1[0]);while(x<=10){write(pipe1[1], &x, sizeof(int));read(pipe2[0], &x, sizeof(int));printf("Parent:%d, read%d\n", getpid(), x++);}close(pipe2[0]);close(pipe1[1]);}return 0;
}
1.2.2 命名管道

位于文件系统中。可以实现不同进程间的双向通信。

mkfifo() 创建命名管道,将产生一个FIFO文件

#include<sys/types.h>
#include<unistd.h>
int mkfifo(const char * pathname, mode_t mode);

pathname:创建的FIFO文件名
mode:规定FIFO文件的读写权限
调用成功时返回0;调用失败返回-1

命名管道必须同时读和写,否则会阻塞

2. System V IPC 进程通信

2.1 IPC

进程间通信(Inter-Process Communication)

2.1.1 查看ipc对象的信息

ipcs [-asmq]
-a:all,查看全部的IPC对象信息
-s:signal,查看信号量集
-m:memory,查看共享内存
-q:queue,查看消息队列

IPC标识符由内核分配给IPC对象,在系统内部唯一,给系统看
IPC关键字由程序员选择,全局唯一,给人看,32字长
每个进程都可以建立一个键值为IPC_PRIVAE的私有IPC对象

ftok() 生成唯一的键值

#include<sys/types.h>
#include<sys/ipc.h>
key_t ftok(char *filename, int id);

filename:文件名,可以使用绝对路径或相对路径
id:整型变量。可通过指定相同文件的文件名和不同的整型变量,生成不同的键值。
调用成功返回所生成的键值;失败返回-1。

/**利用消息队列实现父子进程的通信。父进程创建消息队列,并向消息队列发送消息;子进程接受消息;父进程等待子进程接收消息后删除消息队列。**/
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/msg.h>
#include<string.h>
struct msgbuf{long msgtype;char msgtext[255];
};int create_queue(int key)
{int qid = -1;if(key == -1)perror("ftok");else if( (qid= msgget(key, IPC_CREAT|0666)) < 0)perror("msgget");else return qid;
}void  send_message(int qid, struct msgbuf *msg, char *message)
{strcpy(msg->msgtext, message);if(msgsnd(qid, msg, strlen(msg->msgtext), 0) < 0)perror("msgsnd");
}void recive_message(int qid, struct msgbuf *msg)
{memset(msg->msgtext, 0, 255);if(msgrcv(qid, msg, sizeof(msg->msgtext), msg->msgtype, 0) < 0)perror("msgrcv");
}void distory_queue(int qid)
{struct msqid_ds qds;if(msgctl(qid, IPC_RMID, &qds) < 0)perror("msgctl");
}int main()
{struct msgbuf msg;int qid;pid_t pid;key_t key = ftok(".", 1);   //生成唯一的键值msg.msgtype = 1;qid = create_queue(key);pid = fork();if(pid < 0)perror("fork");else if(pid > 0){send_message(qid, &msg, "This is the input!");printf("Parent: Send to the message queue successfully!\n");printf("The message sent is :%s\n", msg.msgtext);wait(NULL);distory_queue(qid);}else{recive_message(qid, &msg);printf("Clild: Receiving from the message queue:%s\n", msg.msgtext);}return 0;
}

2.2 消息队列

以异步方式为通信频繁但数据量少的进程通信提供服务
存储消息得的线性表,按照先进先出的原则,对数据输入输出。

系统中消息队列最多个数:256
每条消息的最大字节数:8KB
每个队列能容纳的最大字节数:16KB

2.2.1 消息结构模板msgbuf

include/linux/msg.h

struct msgbuf
{long msgtype;   //消息类型char mtext[1];  //消息内容,可自行定义消息的长度
};
2.2.2 基本操作:
  1. 创建或打开消息队列:msgget()
#inclide<sys/types.h>
#include<sys/msg.h>
int msgget(key_t, int flags);

key:键值
flags:标识和权限信息的组合。若标识部分为0,则获取一个已存在的消息队列的标识符;若为IPC_CREAT:如果消息队列不存在则创建,存在则引用。
调用成功,返回消息队列的标识符;否则,返回-1。

  1. 向消息队列发送消息:msgsnd()
#inclide<sys/types.h>
#include<sys/msg.h>
int msgsnd(int msgid, struct msgbuf *msgp, size_t size, int flag);

msgid:消息队列的标识符
msgp:指向消息结构的指针
size:消息内容的长度
flag:发送消息可选标志。若flag为0,则当消息队列满时,发送操作阻塞;若为IPC_NOWAIT时,当消息队列满时,立即返回-1。
调用成功,返回0;否则,返回-1。

  1. 从消息队列读出消息:msgrcv()
#inclide<sys/types.h>
#include<sys/msg.h>
int msgrcv(int msgid, struct msgbuf *msgp, \size_t size, long type, int flag);

msqid:消息队列的标识符
msgp:消息结构指针
size:要读取消息的长度
type:要读取消息的类型
flag:接收消息可选标志。若flag为0,当消息队列为空时,进程阻塞;若flag为IPC_NOWAIT,当消息队列空时,进程不阻塞,立即返回-1;若flag为MSG_NOERROR,当消息长度大于接收缓冲区长度,截断消息返回,小于等于则不接受该消息,出错返回。
调用成功,返回实际读取到的消息数;否则,返回-1。

  1. 删除消息队列:msgctl()
#include <sys/msg.h>
int msgctl(int msgid, int cmd, struct msgid_ds *buf);

msgid:消息队列的标识符
buf:指向msgid_ds结构的指针
cmd:控制命令。若cmd为IPC_RMID, 则删除消息队列;若为IPC_STAT,则获取消息队列的结构,保存在buf所指向的缓冲区中;若为IPC_SET,则按照buf指向的结构来设置该消息队列的结构。
调用成功,返回0;否则,返回-1。
获取和修改消息队列属性信息
查询消息队列描述符
修改消息队列许可权
删除该队列等

2.3 共享主存

2.4 信号量集

远程通信


http://chatgpt.dhexx.cn/article/Qd4dmJWS.shtml

相关文章

进程间通信

文章目录 前言1、进程间通信的目的2、管道1.1 匿名管道1.2 命名管道 3、共享内存2.1 shmget函数2.2 shmctl函数2.3 shmat函数2.4 shmdt函数 4、消息队列5、信号量 前言 进程间通信&#xff08;IPC&#xff0c;InterProcess Communication&#xff09;是指在不同进程之间传播或…

【操作系统】进程通信

什么是进程通信&#xff1f;进程为什么需要通信&#xff1f; 进程通信&#xff1a;进程通信就是进程之间的信息交换。 进程通信的目的&#xff1a; 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程。通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息…

【Linux】进程通信之管道通信详解

&#x1f34e;作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;Linux系统编程 文章目录 一、什么是管道通信1. 管道通信是一种在进程间传递数据的方法2.看看接口&#xff1a;匿名管道和命名管道3. 管道通信的本质是什么&#xff1f; 二、管道通信的实现和深入理解1.如何…

进程通信方式总结与盘点

​ 进程通信是指进程之间的信息交换。这里需要和进程同步做一下区分&#xff0c;进程同步控制多个进程按一定顺序执行&#xff0c;进程通信是一种手段&#xff0c;而进程同步是目标。从某方面来讲&#xff0c;进程通信可以解决进程同步问题。 ​ 首先回顾下我们前面博文中讲到…

《操作系统》实验报告——进程通信

理论知识 Linux——Linux C语言编程基础知识 Linux——进程通信 一、实验目的 (1) 熟悉并掌握管道机制&#xff0c;并实现进程间通信 (2) 熟悉并掌握共享内存机制&#xff0c;并实现进程间通信 二、实验内容 任务一&#xff1a; &#xff08;1&#xff09;阅读以上父子…

多进程通信

多进程&#xff1a; 首先&#xff0c;先来讲一下fork之后&#xff0c;发生了什么事情。 由fork创建的新进程被称为子进程&#xff08;child process&#xff09;。该函数被调用一次&#xff0c;但返回两次。两次返回的区别是子进程的返回值是0&#xff0c;而父进程的返回值则…

进程间通信详解

目录 一.进程间通信介绍 1.进程间通信的目的 2.进程间通信的本质 3.进程间通信分类 二.什么是管道 三.匿名管道 1. 匿名管道只能用于具有亲缘关系的进程之间进行通信&#xff0c;常用于父子。 2.pipe函数 3. 匿名管道的使用 4.管道的读写…

QProcess实现进程通信

QProcess实现进程通信的方式有点类似于管道。 QProcess父进程通过write来写入标准输入stdin&#xff0c;通过ReadyRead信号来接收子进程的消息。 QProcess子进程通过QFile来读取标准输入来接收父进程信息。通过QFile绑定QSocketNotifier来接收标准输入的实时信号&#xff0c;…

进程通信原理

目录 进程通信原理 1、同主机间的消息通讯机制 1.1 管道&#xff08;pipe&#xff09;,流管道(s_pipe)和有名管道&#xff08;FIFO&#xff09; 1.2 信号&#xff08;signal&#xff09; 1.3 消息队列 1.4 共享内存 信号量 套接字&#xff08;socket) 进程间通信各种方式效率比…

Linux进程通信

笔者在学习linux的过程中对linux进程通信进行记录学习。现在在 Linux 中使用较多的进程间通信方式主要有以下几种。 &#xff08;1&#xff09;管道&#xff08;Pipe&#xff09;及有名管道&#xff08;named pipe&#xff09;&#xff1a;管道可用于具有亲缘关系进程间的通信…

【Linux】进程间通信

目录 1. 进程间通信 1.1. 进程间通信的目的 1.2. 如何实现进程间通信 2. 管道通信 2.1. 匿名管道 2.1.1 创建匿名管道 2.1.2 . 深入理解匿名管道 2.2. 命名管道 2.2.1. 创建命名管道 3. system V 标准进程间通信 3.1. 共享内存 3.1.1. 实现原理 3.1.2. 代码实现 3…

认知智能理论三体论介绍简介

三体论是探索研究宇宙&#xff0c;信息和人类大脑三者关系的理论体系。是认知智能的奠基理论体系之一。宇宙和信息&#xff0c;信息和人类大脑&#xff0c;人类大脑和宇宙&#xff0c;三者之间存在着某种未被完全揭示的奥秘。三体论的核心思想体系就是基于宇宙&#xff0c;信息…

认知智能三大技术体系之类脑模型简介

认知智能三大技术体系之类脑模型简介 类脑模型是认知智能核心三大技术体系之一&#xff0c;类脑结构&#xff0c;功能机制的总称。类脑模型技术体系核心指导思想来自认知智能三大奠基理论&#xff0c;脑科学&#xff0c;心理学&#xff0c;逻辑学&#xff0c;情感学&#xff0c…

认知智能CI和人工智能AI的区别介绍简介

认知智能CI和人工智能AI的区别 人工智能和认知智能都是计算机科学的分支学科之一。人工智能是智能时代的第二个阶段&#xff0c;认知智能是智能时代的第三个阶段。认知智能也并不是智能时代发展的最终阶段&#xff0c;最终阶段应该是通用智能强智能时代。 本文主要就人工智能和…

什么是认知智能?

认知智能是计算机科学的一个分支科学&#xff0c;是智能科学发展的高级阶段&#xff0c;它以人类认知体系为基础&#xff0c;以模仿人类核心能力为目标&#xff0c;以信息的理解、存储、应用为研究方向&#xff0c;以感知信息的深度理解和自然语言信息的深度理解为突破口&#…

认知智能是什么?

认知智能是计算机科学的一个分支科学&#xff0c;是智能科学发展的高级阶段&#xff0c;它以人类认知体系为基础&#xff0c;以模仿人类核心能力为目标&#xff0c;以信息的理解、存储、应用为研究方向&#xff0c;以感知信息的深度理解和自然语言信息的深度理解为突破口&#…

人工智能导论

目录 1.1 人工智能导论 1.2 人工智能应用 1.3 人工智能产业发展 1.4 人工智能发展的成功因素 1.5 人工智能迅速发展的技术领域 1.6人工智能的基础知识 1.1 人工智能导论 人工智能的三个层面&#xff1a; 计算智能&#xff1a;能算能存 感知智能&#xff1a;能听会说&…