首页 > 系统相关 >进程间通信-信号-pipe-fifo

进程间通信-信号-pipe-fifo

时间:2023-12-13 09:48:12浏览次数:26  
标签:pipe 函数 程序 FIFO 间通信 fifo 信号 使用 进程

进程间通信-信号-pipe-fifo

编译fifo文件夹的程序

运行fifo文件夹的程序


代码说明

1.consumer.c 文件包含一个用来从 FIFO(命名管道)读取数据的 C 程序。以下是它的主要组件和系统调用的分解:

main() 函数:

  • 初始化文件描述符(pipe_fd)、返回状态(res)、读取数据的缓冲区以及字节数计数(bytes)的变量。
  • 设置 FIFO 以只读模式(O_RDONLY)打开。
  • 使用 open() 系统调用以指定的模式和路径打开 FIFO。
  • 使用循环从 FIFO 读取数据:
  • 使用 read() 系统调用从 pipe_fd 读取数据到 buffer。读取的量存储在 res 中。
  • 它持续读取直到没有更多数据(res 变为 0)。
  • 在读取完成后使用 close() 系统调用关闭 FIFO。
  • 如果打开 FIFO 失败,程序以 EXIT_FAILURE 退出。
  • 程序在成功退出前打印进程 ID 和读取的数据量。
  • 这个程序作为 IPC(进程间通信)场景中的消费者,通过 FIFO 读取生产者进程发送的数据。使用 FIFO 允许进程之间的同步通信。

2.producer.c 文件是一个用于向 FIFO(命名管道)写入数据的 C 程序。以下是其主要组件和系统调用的分析:

main() 函数:

  • 初始化文件描述符(pipe_fd)、返回状态(res)、只写模式(O_WRONLY)、字节数计数(bytes)以及数据缓冲区(buffer)。
  • 检查 FIFO 是否存在(使用 access() 函数)。如果不存在,则创建一个新的 FIFO(使用 mkfifo())。
  • 以只写模式打开 FIFO(使用 open() 系统调用)。
  • 使用循环向 FIFO 写入数据:
  • 使用 write() 系统调用将 buffer 中的数据写入 pipe_fd。写入的量存储在 res 中。
  • 循环直到写入的总量达到 10MB。
  • 如果写入过程中出现错误(res 等于 -1),则打印错误信息并退出。
  • 关闭 FIFO(使用 close() 系统调用)。
  • 如果打开 FIFO 失败,程序以 EXIT_FAILURE 退出。
  • 程序在成功退出前打印进程 ID。
  • 这个程序充当 IPC 场景中的生产者,通过 FIFO 向消费者进程发送数据。通过检查和创建 FIFO,以及循环写入数据,它与消费者进程协调同步通信。 ​

3.testmf.c 文件是一个简单的 C 程序,用于创建 FIFO(命名管道)。以下是其主要组件的分析:

main() 函数:

  • 使用 mkfifo() 系统调用创建一个新的 FIFO。FIFO 的路径被设定为 /tmp/myfifo,权限设置为 0777(意味着任何用户都可以读写该 FIFO)。
  • mkfifo() 返回的结果存储在变量 res 中。如果 res 为 0,表示 FIFO 创建成功,程序会打印一条消息确认 FIFO 已创建。
  • 程序使用 exit(EXIT_SUCCESS) 退出,表明正常终止。
  • 这个程序的作用是创建一个命名管道,它允许 producer.c 和 consumer.c 中的进程进行通信。在 IPC 场景中,通常需要一个独立的程序或进程来创建共享的通信资源(如 FIFO),testmf.c 就承担了这个角色

综上,这三个程序共同构成了一个使用 FIFO 进行进程间通信的示例。testmf.c 负责创建 FIFO,producer.c 将数据写入 FIFO,而 consumer.c 则从 FIFO 读取数据。通过这种方式,两个进程可以安全地共享数据。

编译pipe文件夹下的程序

运行pipe文件夹下的程序







pipe文件夹代码说明

1.listargs.c 是一个用于演示命令行参数处理和标准错误输出的简单 C 程序。

功能:

  • 打印命令行参数的数量和每个参数的值。
  • 向标准错误流(stderr)输出一条消息。

代码结构:

  • main 函数接收两个参数:ac(参数个数)和 av(参数值数组)。
  • 使用 printf 输出参数个数(ac)和每个参数的值(通过遍历 av 数组)。
  • 使用 fprintf 将消息发送到标准错误流(stderr)。

2.分析 pipe.c

pipe.c 是一个演示如何在 C 程序中创建管道和进程分叉(forking)的程序。

功能:

  • 创建一个管道,然后创建一个子进程。
  • 子进程和父进程使用这个管道进行通信。
  • 父进程执行命令行中的第二个参数作为程序,子进程执行第一个参数作为程序。

代码结构:

  • 检查命令行参数的个数,如果不是 3(程序名和两个命令),则显示用法信息并退出。
  • 使用 pipe() 创建一个管道。
  • 使用 fork() 创建一个子进程。
  • 在父进程(pid > 0)中:
  • 关闭管道的写端。
  • 使用 dup2() 将标准输入重定向到管道的读端。
  • 执行 av[2] 指定的程序。
  • 在子进程(pid == 0)中:
  • 关闭管道的读端。
  • 使用 dup2() 将标准输出重定向到管道的写端。
  • 执行 av[1] 指定的程序。
  • 如果任何步骤失败,使用 oops() 函数打印错误信息并退出。

3.分析 pipedemo.c

pipedemo.c 是一个展示如何在 C 程序中使用管道进行数据读写的程序。

功能:

  • 创建一个管道,然后在一个循环中使用这个管道来读写数据。
  • 从标准输入(stdin)读取数据,写入管道的写端。
  • 从管道的读端读取数据,然后写入标准输出(stdout)。

代码结构:

  • 使用 pipe() 创建一个管道。
  • 在一个循环中:
  • 使用 fgets() 从标准输入读取数据到 buf。
  • 使用 write() 将 buf 中的数据写入管道的写端。
  • 将 buf 中的所有字符替换为 'X'。
  • 使用 read() 从管道的读端读取数据回到 buf。
  • 将读取到的数据写入标准输出。
  • 如果任何读写操作失败,打印错误信息并跳出循环。

3.分析 pipedemo2.c

pipedemo2.c 是一个演示如何在 C 程序中使用管道进行父子进程通信的程序。

功能:

  • 创建一个管道,并通过 fork() 创建一个子进程。
  • 子进程定期向管道写入一条消息。
  • 父进程定期从管道读取消息并将其写入标准输出。

代码结构:

  • 使用 pipe() 创建一个管道。
  • 使用 fork() 分叉进程:
  • 在子进程(fork() 返回 0)中:
  • 无限循环,定期向管道写入 CHILD_MESS(“I want a cookie\n”)。
  • 使用 sleep(5) 暂停 5 秒。
  • 在父进程(fork() 返回子进程的 PID)中:
  • 无限循环,定期向管道写入 PAR_MESS(“testing..\n”)。
  • 使用 sleep(1) 暂停 1 秒。
  • 从管道读取数据,并将其写入标准输出。
  • 如果任何读写操作失败,使用 oops() 函数打印错误信息并退出。

4.分析 stdinredir1.c

stdinredir1.c 是一个演示如何在 C 程序中重定向标准输入(stdin)的程序。

功能:

  • 读取并打印来自标准输入的三行文本。
  • 关闭当前的标准输入流(文件描述符 0)。
  • 打开 /etc/passwd 文件,并将其文件描述符重定向到标准输入。
  • 再次读取并打印三行文本,这次是从 /etc/passwd 文件中读取。

代码结构:

  • 使用 fgets() 三次从标准输入读取文本行并打印。
  • 使用 close(0) 关闭当前的标准输入。
  • 使用 open("/etc/passwd", O_RDONLY) 打开 /etc/passwd 文件,并确保它的文件描述符为 0(即标准输入)。
  • 如果文件描述符不是 0,则打印错误信息并退出。
  • 再次使用 fgets() 三次从新的标准输入(现在是 /etc/passwd 文件)读取文本行并打印。

5.分析 testtty.c

testtty.c 是一个非常简单的 C 程序,用于演示向标准输入(通常是终端)写入数据。

功能:

  • 向文件描述符 0(通常是标准输入)写入字符串 "abcde\n"。

代码结构:

  • 定义一个字符串 buf,内容为 "abcde\n"。
  • 使用 write() 函数向文件描述符 0 写入 buf 中的内容。

编译signal文件夹下的程序

运行signal文件夹下的程序




对上述代码进行解释

第一个文件 sigactdemo.c 包含了一个简单的信号处理示例程序。

  • 引入头文件:程序包括标准输入输出库 stdio.h、Unix标准函数库 unistd.h 和信号处理库 signal.h。
  • 定义常量:INPUTLEN 被定义为100,可能用于定义输入缓冲区的大小。
  • 信号处理函数:定义了一个名为 inthandler 的函数,该函数接受一个整数参数(通常是信号编号),打印接收到的信号,然后休眠一段时间,最后再次打印。
  • 主函数 (main):
  • 初始化 sigaction 结构体 newhandler,用于指定信号处理行为。
  • 设置 newhandler 的处理函数为 inthandler。
  • 设置 newhandler 的标志,包括 SA_RESTART(重新启动被信号打断的系统调用)、SA_NODEFER(在处理当前信号时不阻塞当前信号)、SA_RESETHAND(处理完信号后重置信号处理器为默认)。
  • 初始化一个信号集 blocked,并将 SIGQUIT 信号加入到这个集合中。这个集合被设置为 newhandler 的信号掩码,意味着在处理 SIGINT 信号时,SIGQUIT 信号会被阻塞。
  • 调用 sigaction 函数将 SIGINT(通常是通过Ctrl+C产生)的处理方式设置为 newhandler。
  • 程序进入一个无限循环,不断地读取输入并打印。
  • 这个程序演示了如何使用 sigaction 结构体和相关函数来处理信号。当用户按下 Ctrl+C 时,会触发 SIGINT 信号,程序会调用 inthandler 函数来处理该信号。在处理信号的过程中,SIGQUIT 信号会被阻塞。

第二个文件 sigactdemo2.c 包含了一个使用信号来实现睡眠功能的程序。程序的主要内容如下:

  • 引入头文件:程序包括 Unix 标准函数库 unistd.h、信号处理库 signal.h 和标准输入输出库 stdio.h。
  • 信号处理函数:定义了一个名为 sig_alrm 的函数,这个函数没有实际操作(空函数体),用于捕获 SIGALRM 信号。
  • 自定义的睡眠函数 (mysleep):
  • 接受一个表示秒数的参数 nsecs。
  • 定义和设置一个 sigaction 结构体 newact,用于指定 SIGALRM 信号的处理行为(在这里是 sig_alrm 函数)。
  • 调用 alarm 函数来设置一个定时器,当定时器到达指定的秒数时,会发送 SIGALRM 信号。
  • 调用 pause 函数使进程暂停,直到捕获到一个信号。
  • 当 SIGALRM 被捕获后,pause 返回,mysleep 函数再次调用 alarm 函数以获取剩余的睡眠时间。
  • 最后,将 SIGALRM 的处理方式恢复为原始状态,并返回未睡足的时间。
  • 主函数 (main):
  • 使用无限循环,每两秒打印一次信息,演示 mysleep 函数的使用。
  • 这个程序展示了如何结合信号处理和 alarm 函数实现一个简单的睡眠机制。当 alarm 计时器触发 SIGALRM 信号时,由于 sig_alrm 函数不执行任何操作,所以程序继续执行,从 pause 返回。

第三个文件 sigdemo1.c 包含了一个基本的信号处理示例程序。这个程序的主要内容包括:

  • 引入头文件:程序包括标准输入输出库 stdio.h 和信号处理库 signal.h。
  • 信号处理函数:定义了一个名为 f 的函数,该函数接受一个信号编号参数,并在被调用时打印 "OUCH!"。
  • 主函数 (main):
  • 使用 signal 函数将 SIGINT 信号(通常由 Ctrl+C 触发)的处理方式设置为 f 函数。
  • 进入一个循环,循环五次,每次循环打印 "hello" 并休眠两秒。
  • 这个程序是对信号处理的一个非常基础的演示。当用户在程序运行时按下 Ctrl+C,SIGINT 信号被触发,程序调用 f 函数来处理这个信号,从而打印 "OUCH!"。。 ​

第四个文件 sigdemo2.c 展示了如何忽略一个信号。这个程序的主要内容如下:

  • 引入头文件:程序包括标准输入输出库 stdio.h 和信号处理库 signal.h。
  • 主函数 (main):
  • 使用 signal 函数将 SIGINT 信号(通常由 Ctrl+C 触发)的处理方式设置为 SIG_IGN,意味着程序将忽略这个信号。
  • 打印 "you can't stop me!",然后进入一个无限循环。
  • 在循环中,每秒休眠一次,并打印 "haha"。
  • 这个程序通过将 SIGINT 信号的处理方式设置为 SIG_IGN,展示了如何使程序对 Ctrl+C 忽视不理。由于这种设置,当用户尝试使用 Ctrl+C 中断程序时,程序将不会响应,而是继续运行并每秒打印 "haha"。

第五个文件 sigdemo3.c 展示了如何处理多种信号。这个程序的主要内容包括:

  • 引入头文件:程序包括标准输入输出库 stdio.h、字符串处理库 string.h、信号处理库 signal.h 和 Unix 标准函数库 unistd.h。
  • 定义常量:INPUTLEN 被定义为100,用于定义输入缓冲区的大小。
  • 信号处理函数:定义了两个处理函数 inthandler 和 quithandler,这两个函数在接收到信号时打印信息,休眠一段时间,然后再次打印。
  • 主函数 (main):
  • 使用 signal 函数分别将 SIGINT(通常由 Ctrl+C 触发)和 SIGQUIT(通常由 Ctrl+\ 触发)的处理方式设置为 inthandler 和 quithandler。
  • 进入一个循环,提示用户输入消息,并使用 read 函数读取输入。
  • 如果读取到的字符数为 -1,则打印错误信息;否则打印用户输入的内容。
  • 当用户输入的内容以 "quit" 开头时,程序退出循环并结束。
  • 这个程序演示了如何为不同的信号设置不同的处理函数。用户在程序运行时可以通过发送特定的信号(如 Ctrl+C 或 Ctrl+\)来触发相应的处理函数。同时,它还提供了一个简单的用户交互方式,允许用户通过输入来控制程序流程。

标签:pipe,函数,程序,FIFO,间通信,fifo,信号,使用,进程
From: https://www.cnblogs.com/wujiuchun/p/17898343.html

相关文章

  • Tekton pipelineruns 基础
    pipelineruns概述PipelineRun允许你在集群上实例化和执行Pipeline。一个Pipeline指定一个或多个Tasks,按照期望的执行顺序执行。PipelineRun按照指定的顺序执行Pipeline中的Tasks,直到所有Tasks都成功执行或失败。PipelineRun会自动为Pipeline中的每个Task创建相应的taskrun。pipeli......
  • Tekton Pipelines 基础
    Pipelines概述Pipeline是Tasks的集合,作为持续集成流的一部分,您可以定义并按照特定的执行顺序排列这些Tasks。Pipeline中的每个Tasks在Kubernetes集群上作为Pod执行。您可以配置各种执行条件来满足您的业务需求。Pipeline使用When表达式when表达式input:被评估的内容,支持使用静态......
  • 进程间通信-信号-pipe-fifo
    编译运行FifoConsumerProducer一起运行Testmfpipe文件夹PipeListarg理解()Pipe概念:管道是一种在两个进程之间进行通信的机制。个进程的输出可以通过管道传递给另一个进程的输入创建:在C语言中,可以使用pipe系统调用创建管道。管道有两端,一个用千写入,一个用干读......
  • 进程间通信-信号-pipe-fifo(课上测试)
    一.运行结果二.代码说明consumer.c该程序是一个使用FIFO(命名管道)进行进程间通信的示例。首先定义了FIFO的名称和缓冲区的大小。然后在主函数中,打开了一个以只读方式打开的FIFO,并读取FIFO中的数据直到读取完毕,最后关闭FIFO。相关系统调用说明:1.open:打开FIFO文件,返回文......
  • Pipeline模式应用
    本文记录Pipeline设计模式在业务流程编排中的应用前言Pipeline模式意为管道模式,又称为流水线模式。旨在通过预先设定好的一系列阶段来处理输入的数据,每个阶段的输出即是下一阶段的输入。本案例通过定义PipelineProduct(管道产品),PipelineJob(管道任务),PipelineNode(管道节点),完成一整......
  • day11 Jenkins Pipeline语法-Jenkins基于Gitlab的授权认证 (4.3.1-4.4)
    一、JenkinsPipeline语法上JenkinsPipeline语法Jenkins有多种方式实现交付流水线。其中,JenkinsPipeline是一种比较流行的方式,它提供一个DSL(DomainSpecificLanguage的缩写,)来描述交付流水线。官网地址:https://www.jenkins.io/doc/book/pipeline/syntax/1、什么是Jenkin......
  • Vue3的手脚架使用和组件父子间通信-插槽(Options API)学习笔记
    VueCLI安装和使用全局安装最新vue3npminstall@vue/cli-g升级VueCLI:如果是比较旧的版本,可以通过下面命令来升级npmupdate@vue/cli-g通过脚手架创建项目vuecreate01_product_demoVue3父子组件的通信父传子父组件<template><div><divclass="item"v-for="(item,in......
  • VideoPipe可视化视频结构化框架更新总结(2023-12-5)
    项目地址:https://github.com/sherlockchou86/video_pipe_c往期文章:https://www.cnblogs.com/xiaozhi_5638/p/16969546.html很久没有更新了,本次记录4个,有兴趣的扫码加群交流。支持rtsp推流现在pipeline末尾支持以rtsp的方式推流,注意不需要额外的rtsp服务器,自己主机就是rtspser......
  • Tekton pipelineruns 基础
    pipelineruns概述PipelineRun允许你在集群上实例化和执行Pipeline。一个Pipeline指定一个或多个Tasks,按照期望的执行顺序执行。PipelineRun按照指定的顺序执行Pipeline中的Tasks,直到所有Tasks都成功执行或失败。PipelineRun会自动为Pipeline中的每个Task创建相应的taskrun。pi......
  • Tekton Pipelines 基础
    Pipelines概述Pipeline是Tasks的集合,作为持续集成流的一部分,您可以定义并按照特定的执行顺序排列这些Tasks。Pipeline中的每个Tasks在Kubernetes集群上作为Pod执行。您可以配置各种执行条件来满足您的业务需求。Pipeline使用When表达式when表达式input:被评估的内容,支持使用......