进程间通信--学习笔记

这篇具有很好参考价值的文章主要介绍了进程间通信--学习笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

# 进程间通信

--pipe、FIFO、共享内存、消息队列、信号量

pipe(无名管道)

​ 只能实现有亲缘关系进程之间的通信,它是单向的,

进程间通信--学习笔记

int pipe(int piped[2])  //创建管道

fd[0] : 读文件,fd[1] :写文件。

之后可以用open()、write()函数进行对管道进行操作,

创建管道要在fork()之前以保证父子进程操作是同一个管道。

FIFO(有名管道)

int mkfifo(const char* pathname,mode_t mode) 	//创建有名管道函数
mkfifo [option] [name] 							 //创建有名管道命令
int access (const char* pathname,int mode)		//可用来检查管道的权限

mode :

​ F_OK : 检查文件是否存在

​ R_OK: 检查读权限

​ W_OK: 检查写权限

​ X_OK : 检查执行权限

成功时返回 0,失败时返回 -1

管道与普通文件的区别之一,管道文件使用read()时,文件为空时进程会阻塞

信号通信

进程间通信--学习笔记

信号的发送 : kill(),raise()

int kill(pid_t pid,int sig);              
int raise(int sig);

raise()函数等价于kill(getpid(),sig);

atoi() //将字符串转化为整形

alarm()函数是一种系统调用,用于设置一个闹钟。当指定的时间过去之后,会发送一个信号给当前进程。

alarm()函数的原型是:

int alarm(int seconds);

alarm()`函数接受一个整数参数,表示闹钟应该在多少秒后响起。如果参数为0,那么闹钟将立即响起。如果函数成功执行,将返回0。如果函数执行失败,将返回-1。

当闹钟响起时,当前进程会收到一个SIGALRM信号。默认情况下,该信号将终止进程。但是,您可以使用信号处理函数来捕获SIGALRM信号并执行自定义操作。

信号的处理:

三种方式: 1)系统默认 2) 忽略 3) 捕获

sighandler_t signal(int signum,sighandler_t handler);

参数1:要进行处理的信号,shell中可通过kill -l 命令查看,

参数2:处理的方式

  • SIG_DFL (默认)

  • SIG_IGN(忽略)

  • myfun(自己定义的函数)

共享内存

进程间通信--学习笔记

在C语言中,共享内存是一种让不同进程可以访问同一块物理内存的技术。通过共享内存,不同进程可以相互通信并共享数据。

在Unix/Linux系统中,我们可以使用系统调用shmget、shmat、shmdt和shmctl来创建、映射、解除映射和删除共享内存段。

int shmget(ket_t key,size_t size,int shmflg); //创建共享内存

参数:

key_t key : IPC_PRIVATE或者是ftok()函数的返回值。(用ftok()函数后面要加上IPC_CREAT)

size_t size : 共享内存的大小

int shmflg : 权限

返回值:

成功返回内存的标识符,失败返回-1

key_t ftok(const char *pathname, int id);

这个函数根据文件名(pathname)和可选的标识符(id)来生成一个唯一的键值(key_t类型)。这个键值可以用来在后续的调用中识别同一共享内存段。

id参数通常是一个常数,用来区分不同的进程和不同的文件。如果id参数为0,那么ftok()函数会忽略它,只使用文件名作为唯一的键值。

如果函数成功执行,它将返回一个唯一的键值。如果失败,它将返回-1。

注意,ftok()函数并不是线程安全的,因为它返回的是静态内存。在多线程环境中,如果多个线程同时调用ftok()函数,可能会导致冲突。

void *shmat(int shmid ,const void * shmaddr,int shmflg);

参数:

int shmid : 共享内存的标识符

void *shmaddr: 映射到的地址,一般写NULL

int shmflg : 通常为0 表示内存可读可写 ,或者SHM_RDONLY表示只读

返回值:

成功返回共享内存映射到进程中的地址,失败返回-1.

int shmdt(const void *shmaddr)

成功返回0,失败返回-1.

只是删除进程中的地址映射,不会删除内核里面的共享内存对象,可以用shmctl()函数删除内核里的对象。

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

参数:

int shmid : 要操作的共享内存的标识符

int cmd : IPC_STAT(获取对象属性)

​ IPC_SET(设置对象属性)

​ IPC_RMID(删除对象)

shmid_ds *buf : 指定IPC_STAT时用来保存或设置的属性.

消息队列

进程间通信--学习笔记

在C语言中,消息队列是一种进程间通信(IPC)的机制,它允许进程之间发送和接收消息。消息队列是操作系统内核维护的一种数据结构,它可以在不同的进程之间传递数据。

在C语言中,使用消息队列进行通信需要使用系统调用 msgget()msgsnd()msgrcv()msgctl()

int msgget(key_t key,int msgflg);

参数:

key_t key : 消息队列相关的key值

int msgflg: 访问权限

队列时链式的,所以不用像共享内存一样指定队列的大小

int msgctl(int msgid,int cmd,strcut msgid_ds *buf);

参数:

int msgid : 消息队列的ID

int cmd : 同共享内存

buf : 消息队列的缓冲区

返回值:

成功返回0,失败返回-1.

msgsnd()函数是在Unix/Linux环境中使用的,它属于POSIX消息队列API。这个函数用于发送消息到已经创建的队列中。

int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);

参数:

int msqid : 消息队列ID

void *msgp : 指向消息类型的指针

size_t msgsz : 发送消息的字节数

int msgflg : 如果为0 阻塞发送,IPC_NOWAIT: 非阻塞发送

返回值:

成功返回0 失败返回 -1

size_t msgrcv(int msqid,void * msgp,size_t msgsz,long msgtyp,int msgflg);

参数:

  1. msqid:这是消息队列的标识符(message queue identifier),即我们要从中接收消息的消息队列的描述符。
  2. msg_ptr:这是一个指向接收缓冲区的指针,该缓冲区用于存储接收的消息。这个缓冲区应该足够大,以容纳消息的最大长度,这个长度通常由消息队列的属性mq_msgsize给出。
  3. msg_len:这是msg_ptr指向的缓冲区的大小(以字节为单位)。这个值应该等于或大于消息的最大长度。
  4. msg_prio:这是一个指向整数的指针,该整数用于存储接收消息的优先级。消息的优先级是一个0到MQ_PRIO_MAX(通常为32767)的整数。
  5. msg_flags:这是一个标志位,用于控制函数的行为。标志可以是以下值的组合或之一:MSG_NOERROR(如果消息被截断,不返回错误)、MSG_PEEK(仅查看消息,不移除)和MSG_WAITALL(等待直到接收到足够长度的消息)。

这个函数的返回值是接收的消息的长度(以字节为单位),如果成功;如果发生错误,则返回-1并设置errno。可能的错误包括但不限于EBADF(无效的队列描述符)、EINVAL(无效的标志)、EMSGSIZE(缓冲区太小)和ETIMEDOUT(在无消息可用时超时)

信号量

用来保护共享资源

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

参数:

  • key:用于标识信号量的键。这个键可以是正整数或字符串,其用途是标识要获取或创建的信号量。如果key是正整数,那么它代表了一个已经存在的信号量;如果是零,则表示创建一个新的未命名信号量;如果是负数,则表示创建一个新的命名信号量,名字为-key

  • nsems:指定要获取或创建的信号量数量。通常来说,这个值应该为1,表示只获取或创建一个信号量。

  • semflg
    

    :指定信号量的属性。这个参数可以是以下标志的组合或之一:

    • IPC_CREAT:如果信号量不存在,则创建新的信号量。
    • IPC_EXCL:如果信号量已经存在,则不执行任何操作并返回错误。
    • 0:如果指定了IPC_CREAT标志,则该值必须是零。

返回值:

  • 如果函数执行成功,返回值为非负整数,代表成功获取或创建的信号量的数量。对于未命名的信号量,返回值是有效的信号量ID;对于命名的信号量,返回值是已成功连接的信号量数量。

  • 如果函数执行失败,返回值为-1,并且错误代码被存储在errno中。可能的错误包括:EACCES(权限不足)、EEXIST(键已经存在)、EINVAL(无效的参数)、ENOENT(键不存在)和ENOMEM(内存不足)。

semctl()函数是用于控制信号量的函数之一。它是Unix/Linux操作系统中用于进程间通信(IPC)的一种机制。

int semctl(int semid, int semnum, int cmd, union semun arg);

参数说明:

  • semid:信号量标识符(semid),由semget()函数获取。
  • semnum:信号量编号,通常为0,表示对第一个信号量进行操作。
  • cmd: IPC_STAT,IPC_SET,IPC_RMID,SETVAL(设置信号量的值)
  • arg:union类型的结构体,包含要传递给命令的参数。具体结构体定义如下:
union semun {  
    int val;            /* 用于SETVAL和GETVAL操作,可能是信号量的当前值。 */  
    struct semid_ds *buf;  /*用于SETALL和GETALL操作,这个指针指向一个semid_ds结构体,*/
    unsigned short *array;   /* 同样用于SETALL和GETALL操作,这个指针指向一个unsigned short类型的数组,可能是多个信号量的列表。 */  
    void *ptr;            /* 用于GETOPT操作,可能是一个任意的指针,用于传递额外的参数 */  
};

返回值:

  • 如果函数执行成功,返回值为0;
  • 如果函数执行失败,返回值为-1,并设置errno为相应的错误代码。

semop()函数是Unix/Linux操作系统中用于对信号量进行操作的函数之一。它是进程间通信(IPC)的一种机制,用于实现进程间的同步和互斥。

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

参数说明:

  • semid:信号量标识符(semid),由semget()函数获取。
  • sops:指向sembuf结构体数组的指针,用于指定要对信号量执行的操作。
  • nops:数组中要执行的操作数量。

sembuf结构体定义如下:文章来源地址https://www.toymoban.com/news/detail-747209.html

struct sembuf {  
    unsigned short sops;  // 操作类型(如SEM_ waits 或 SEM_posts)  
    unsigned short _pad;   // 填充,使用时必须是0  
    int sem_num;           // 信号量编号(在semid中)  
    int sem_op;             // 操作值(-1为减,1为加)  
    int sem_flg;            // 标志位(如IPC_NOWAIT为非阻塞,0表示阻塞)  
};

到了这里,关于进程间通信--学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【探索Linux】—— 强大的命令行工具 P.14(进程间通信 | 匿名管道 | |进程池 | pipe() 函数 | mkfifo() 函数)

    当今计算机系统中,进程间通信扮演着至关重要的角色。随着计算机系统的发展和复杂性的增加,多个进程之间的协作变得更加必要和常见。进程间通信使得不同进程能够共享资源、协调工作、传输数据,并实现更加复杂和强大的功能。本文将深入探讨进程间的通信,以及管

    2024年02月05日
    浏览(60)
  • 进程间通信--学习笔记

    # 进程间通信 --pipe、FIFO、共享内存、消息队列、信号量 ​只能实现有亲缘关系进程之间的通信,它是单向的, fd[0] : 读文件,fd[1] :写文件。 之后可以用open()、write()函数进行对管道进行操作, 创建管道要在fork()之前以保证父子进程操作是同一个管道。 mode : ​F_OK : 检查文件是

    2024年02月05日
    浏览(30)
  • (学习笔记-进程管理)进程间有哪些通信方式?

    每个进程的用户地址空间都是独立的,一般而言是不能互相访问的,但内核空间时每个进程都共享的,所以进程之间要通信必须通过内核   在Linux命令中 [ | ]  这个竖线就是一个 管道 。 它的功能是讲前一个命令(ps auxf)的输出,作为后一个命令(grep mysql)的输入,从这功

    2024年02月13日
    浏览(30)
  • 【Linux】进程通信 — 共享内存

    上一章我们由进程通信,引入并讲述了管道,匿名管道和命名管道和匿名管道。本章我们将继续讲解进程通信的另一种方式,通过共享内存的方式来进行进程间的通信。还要学习几个系统调用接口,并用代码实现两个进程通过共享内存来进行通信。目标已经确定,接下来就要

    2024年02月15日
    浏览(34)
  • 进程间通信之共享内存

    进程间通信之共享内存 共享内存是最快的进程间通信形式,是通过调用系统接口(shmget)由操作系统开辟一块物理内存,然后通过页表映射到进程地址空间中,进而使得用户可以使用这块内存,两个进程间共用一块共享内存通过数据交互就可以建立通信。 未创建共享内存之前

    2024年02月07日
    浏览(26)
  • Linux进程通信——共享内存

    两个进程的PCB创建虚拟地址空间然后映射到物理内存中,每个进程因为是独立的,所以在物理内存中的地址也不同。 那么共享内存是怎么做到的呢? 首先先在物理内存中申请一块内存。 然后讲这块内存通过页表映射分别映射到这两个进程的虚拟地址空间内,让这两个进程都

    2024年02月01日
    浏览(36)
  • (26)Linux 进程通信之共享内存(共享储存空间)

    共享内存是System V版本的最后一个进程间通信方式。 共享内存,顾名思义就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为同一段物理内存。进程可以将同一段物理内

    2024年01月16日
    浏览(31)
  • Linux——进程通信之共享内存

    目录 一.  回顾上文 二.共享内存 1.定义 2.特点: 3.实现步骤: 如下为成功链接共享内存使用权的完整步骤: 4.函数介绍         4.1shmget函数         4.1.2参数介绍                4.2ftok函数:         4.2.1参数介绍                 关于ftok(); shmget();函数的

    2024年02月12日
    浏览(41)
  • Linux 共享内存mmap,进程通信

    进程间通信是操作系统中重要的概念之一,使得不同的进程可以相互交换数据和进行协作。其中,共享内存是一种高效的进程间通信机制,而内存映射(mmap)是实现共享内存的一种常见方法。 存储映射 I/O 是 一个磁盘文件 与 存储空间中的一个缓冲区相映射 。于是, 当从缓

    2024年02月13日
    浏览(29)
  • 进程间通信--共享内存详解【Linux】

    本文详细讲解了共享内存的原理和使用,并且通过实例代码角度来深度理解共享内存,下面就让我们开始吧。 数据传输:一个进程需要将它的数据发送给另一个进程 资源共享:多个进程之间共享同样的资源。 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(

    2024年02月02日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包