当前位置: 首页 > news >正文

【学习嵌入式-day-27-进程间通信】

线程间循环打印ABC,使用信号量决定打印顺序

#include "../head.h"sem_t sem_a;
sem_t sem_b;
sem_t sem_c;void *thread1(void *arg)
{while(1){sem_wait(&sem_a);printf("A\n");sem_post(&sem_b);}return NULL;
}
void *thread2(void *arg)
{while(1){sem_wait(&sem_b);printf("B\n");sem_post(&sem_c);}return NULL;
}
void *thread3(void *arg)
{while(1){sem_wait(&sem_c);printf("C\n");sem_post(&sem_a);}return NULL;
}int main(void)
{pthread_t tid1;pthread_t tid2;pthread_t tid3;sem_init(&sem_a, 0, 1);sem_init(&sem_b, 0, 0);sem_init(&sem_c, 0, 0);pthread_create(&tid1, NULL, thread1, NULL);pthread_create(&tid2, NULL, thread2, NULL);pthread_create(&tid3, NULL, thread3, NULL);pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_join(tid3, NULL);sem_destroy(&sem_a);sem_destroy(&sem_b);sem_destroy(&sem_c);return 0;
}

进程间通信

概念

  • 进程空间是独立的,包含文本段、数据段和系统数据段
  • 多个进程没有共享的用户空间,进程是操作系统资源分配的最小单元
  • 只能利用内核实现进程间通信

进程间通信常用的方式

传统Unix系统中的通信方式

  • 管道
  • 信号

SYS V分支中的通信方式

  • 消息队列
  • 共享内存
  • 信号量数组(信号灯)

BSD分支中的通信方式

  • 本地域套接字

管道(内核缓存区)

分类

  • 有名管道
  • 无名管道(只能用于具有亲缘关系的进程间通信)

无名管道

  • 原理:
    • 无名管道是一段内核缓存区
    • 父进程通过Pipe创建无名管道
    • 只有该父进程的子进程才能继承文件描述符,
  • 函数接口
    • pipe :

                创建无名管道,0读,1写   

#include "../head.h"int main(void)
{int pipefd[2];int pipefd2[2];int ret = 0;pid_t pid;char tmpbuff[4096] = {0};char tmpbuff2[4096] = {0};ret = pipe(pipefd);if(-1 == ret || pipe(pipefd2) == -1){perror("fail to pipe");return -1;}pid = fork();if(-1 == pid){perror("fail to fork");return -1;}if(0 == pid)    //子进程{strcpy(tmpbuff, "hello world");write(pipefd[1], tmpbuff, strlen(tmpbuff));read(pipefd2[0], tmpbuff2, sizeof(tmpbuff2));printf("tmpbuff2 = %s\n", tmpbuff2);}else if(pid > 0)    //父进程{read(pipefd[0], tmpbuff, sizeof(tmpbuff));printf("tmpbuff = %s\n", tmpbuff);strcpy(tmpbuff2, "thank you");write(pipefd2[1], tmpbuff2, strlen(tmpbuff2));}close(pipefd[0]);close(pipefd[1]);close(pipefd2[0]);close(pipefd2[1]);return 0;
}
  • 管道操作特性
    • 管道中至少有一个写端
      • 读取数据时,如果管道中有数据,则直接读出
      • 管道中没有数据, 则阻塞等待有数据写入才能读出
    • 管道中没有写端
      • 读取数据时,管道中有数据,直接读出
      • 没有数据,不阻塞等待直接向下执行
    • 管道中至少有一个读端
      • 写入数据时,如果管道没有写满,则直接写入
      • 管道存满,则阻塞等待有数据读出,才能继续写入
    • 管道中没有读端
      • 写入数据时,会产生管道破裂的信号导致进程任务异常退出

有名管道

与无名管道区别
  • 有名管道有名字,可以通过名字找到该管道
  • 可以用于任意进程间的通信
  • 进程间通信最简单、易实现的方式

操作方式
  • 进程一使用open以 读、写、读写方式打开管道文件
  • 进程二使用open以读、写、读写方式打开管道文件
  • 两个进程可以通过向管道文件中读写数据实现进程的通信
函数接口

mkfifo

循环实现,write.c从终端写字符串,read.c从终端接收,再往终端写字符串,write接收

发一次,收一次,循环

//read.c
#include "../head.h"int main(void)
{int fdr = 0;int fdw = 0;char tmpbuff[4096] = {0};mkfifo("./myfifo1", 0777);mkfifo("./myfifo2", 0777);fdr = open("./myfifo1", O_RDONLY);//可以直接设置为只读RDWRif(-1 == fdr){perror("fail to open");return -1;}fdw = open("./myfifo2", O_WRONLY);if(-1 == fdw){perror("fail to open");return -1;}printf("管道打开成功\n");while(1){memset(tmpbuff, 0, sizeof(tmpbuff));//清零read(fdr, tmpbuff, sizeof(tmpbuff));printf("RECV:%s\n", tmpbuff);memset(tmpbuff, 0, sizeof(tmpbuff));m_fgets(tmpbuff);write(fdw, tmpbuff, strlen(tmpbuff));}close(fdr);close(fdw);return 0;
}
//wirte.c#include "../head.h"int main(void)
{int fdr = 0;int fdw = 0;char tmpbuff[4096] = {0};mkfifo("./myfifo1", 0777);mkfifo("./myfifo2", 0777);fdw = open("./myfifo1", O_WRONLY);if(-1 == fdr){perror("fail to open");return -1;}fdr = open("./myfifo2", O_RDONLY);if(-1 == fdw){perror("fail to open");return -1;}printf("管道打开成功\n");while(1){memset(tmpbuff, 0, sizeof(tmpbuff));m_fgets(tmpbuff);write(fdw, tmpbuff, strlen(tmpbuff));memset(tmpbuff, 0, sizeof(tmpbuff));read(fdr, tmpbuff, sizeof(tmpbuff));printf("RECV:%s\n", tmpbuff);}close(fdr);close(fdw);return 0;
}

信号

概念

  • linux系统中的信号,主要实现应用层和内核层之间的信号通知
  • 应用层和内核层之间通信的信号,根据含义分为很多不同的信号
  • 信号主要用于多个进程任务间的时间通知
  • 信号可以用于异步通信
  • 信号的类型
    • 使用kill-l查看信号的类型

信号的处理方式

  • 缺省:信号来了,按照默认方式处理
  • 忽略:信号来了,不处理信号,忽略信号
  • 捕捉:信号来了,按照用户自己定义的方式处理信号
  • 9号信号(SIGKILL)和19号信号(SIGSTOP),不能被忽略和捕捉的

函数接口

signal

从终端输入 ctrl + C打印打印 SIGINT信号来了
输入 ctrl + \打印 SIGQUIT信号来了
输入 ctrl + z打印 SIGTSTP信号来了

#include "../head.h"void handler1(int signo)
{printf("SIGNINT信号来了\n");
}
void handler2(int signo)
{printf("SIGQUIT信号来了\n");
}
void handler3(int signo)
{printf("SIGTSTP信号来了\n");
}
int main(void)
{void(*pret1)(int) = NULL;void(*pret2)(int) = NULL;void(*pret3)(int) = NULL;pret1 = signal(SIGINT, handler1);if(SIG_ERR == pret1){perror("fail to signal");return -1;}pret2 = signal(SIGQUIT, handler2);if(SIG_ERR == pret2){perror("fail to signal");return -1;}pret3 = signal(SIGTSTP, handler3);if(SIG_ERR == pret3){perror("fail to signal");return -1;}while(1){}return 0;
}

alarm

#include "../head.h"void handler(int signo)
{printf("SIGALRM信号来了\n");alarm(5);return;
}int main(void)
{signal(SIGALRM, handler);alarm(5);while (1){printf("正在运行...\n");sleep(1);}return 0;
}
kill

#include "../head.h"pid_t pid;void handler_parent(int signo)
{if (SIGQUIT == signo){kill(pid, SIGUSR2);}else if (SIGUSR1 == signo){printf("父进程:收到子进程发送的信号了\n");}return;
}void handler_child(int signo)
{if (SIGINT == signo){kill(getppid(), SIGUSR1);}else if (SIGUSR2 == signo){printf("子进程:收到父进程发送的信号了\n");}return;
}int main(void)
{pid = fork();if (-1 == pid){perror("fail to fork");return -1;}if (0 == pid){signal(SIGUSR2, handler_child);signal(SIGINT, handler_child);signal(SIGQUIT, SIG_IGN);}else if (pid > 0){signal(SIGUSR1, handler_parent);signal(SIGQUIT, handler_parent);signal(SIGINT, SIG_IGN);}while (1){}return 0;
}

http://www.dtcms.com/a/337745.html

相关文章:

  • 开放最短路径优先协议
  • Read View 在 MVCC 里如何工作的?
  • DSP音频算法工程师技能2
  • IDE开发系列(2)扩展的IDE框架设计
  • GNhao/GN号,海外SIM号怎么注册详细步骤!
  • 纯前端表格控件SpreadJS v18.0 Update1正式发布——集成AI智能化插件
  • 大数据计算引擎(一)——Spark
  • gdb的load命令和传给opeocd的monitor flash write_image erase命令的区别
  • 如何实现前后端交互以及方法传参中传字段和传对象的区别和方法。
  • 音乐怎么测试?正在播放音乐,中途拔掉u盘,再次插上u盘,是怎么播放的?
  • 低端设备加载webp ANR
  • JavaScript 常用事件总结汇总
  • 前端css学习笔记7:各种居中布局空白问题
  • Ethan独立开发新品速递 | 2025-08-18
  • 开发避坑指南(28):Spring Boot端点检查禁用失效解决方案
  • 【Linux操作系统】简学深悟启示录:进程状态优先级
  • 遨游三防科普|三防平板是指哪三防?应用在什么场景?
  • linux对外提供snmp服务
  • Pytest项目_day18(读取ini文件)
  • Spring Boot 实用小技巧:多级缓存(Caffeine + Redis)- 第545篇
  • 如何解决机器翻译的“幻觉“问题(Hallucination)?
  • 当AI学会“思考”:大语言模型背后的智能本质与伦理边界
  • 【提示词技巧】通用提示词原则介绍
  • Linux学习-软件编程(进程间通信1)
  • ROS 2 中用于建图的一些 topic
  • PyTorch神经网络工具箱(优化器)
  • buuctf:护网杯_2018_gettingstart、oneshot_tjctf_2016
  • llamafactory使用qlora训练
  • VectorDB+FastGPT一站式构建:智能知识库与企业级对话系统实战
  • 使用LLaMA-Factory对大模型进行微调-详解