linux高级编程:线程(二)、进程间的通信方式
线程:
回顾线程(一):
1.线程间通信问题
线程间共享同一个资源(临界资源)
互斥:
排他性访问
linux系统 -- 提供了Posix标准的函数库 -- 互斥量(互斥锁)
原子操作:---
机制:
加锁 -- 解锁
锁 --- 操作系统 --- (实现的机制,需要操作系统来
| - 加锁 -- 用户态 -- 切换到(耗时) -- 内核态 -- 获得了 -- 内核态 -- 用户态 -- 解锁 |
函数:
pthread_mutex_t mutex;
pthread_mutex_init();
pthread_mutex_lock();
pthread_mutex_trylock(); // 尝试获得锁,若没获得则返回非0值。

pthread_mutex_unlock();
pthread_mutex_destroy();
线程的同步:
同步 ==》有 一定先后顺序的 对资源的排他性访问。
要同步的原因:互斥锁可以控制排他访问但没有次序。
信号量 --- 实现线程间的同步.
来源 生活 --- 交通信号灯
信号量的分类:
1、无名信号量 ==》线程间通信
2、有名信号量 ==》进程间通信
同步机制:
信号量(个数) --- 反映的是资源的数量
考虑的时候,站在使用这的角度考虑
站在a的角度考虑。。。。。。
框架:
1. 信号量的定义 sem_t sem //造了一类资源
2. 信号量的初始化 sem_init
3. 信号量的PV操作 (核心) sem_wait()/ sem_post()
4. 信号量的销毁。 sem_destroy

信号量函数:
1、定义
sem_t 名字;
2、初始化
int sem_init(sem_t *sem, int pshared, unsigned int value);
功能:
将已经定义好的信号量赋值。
参数:
@sem 要初始化的信号量
@pshared
pshared = 0 ;表示线程间使用信号量(一般填这个)
!=0 ;表示进程间使用信号量
@value:
信号量的初始值,一般无名信号量(一开始的资源的个数)
都是二值信号量,0 1
0 表示红灯,进程暂停阻塞
1 表示绿灯,进程可以通过执行
也可以是多个,变成计数信号量
返回值:
成功 0,失败 -1;
3、PV操作
int sem_wait(sem_t *sem); //p操作
功能:
判断当前sem信号量是否有资源可用。
如果sem有资源(==1),则申请该资源,程序继续运行
如果sem没有资源(==0),则线程阻塞等待,一旦有资源
则自动申请资源并继续运行程序。
消耗了这个sem,就没有了
注意:sem 申请资源后会自动执行 sem = sem - 1;
参数:
@sem 要判断的信号量资源
返回值:
成功 0 ,失败 -1
int sem_post(sem_t *sem); //V操作
功能:
函数可以将指定的sem信号量资源释放
并默认执行,sem = sem+1;
线程在该函数上不会阻塞。
产生了这个sem就有了,可以由wait(sem)接受去消耗
参数:
@sem 要释放资源的信号量
返回值:
成功 0,失败 -1;
4、销毁
int sem_destroy(sem_t *sem);
练习: hello world
#include<stdio.h>
#include<semaphore.h>
#include<errno.h>
#include<pthread.h>
#include<stdlib.h>sem_t sem_h;
sem_t sem_w;void *do_hello(void *arg)
{while(1) {sem_wait(&sem_h);printf("hello ");sem_post(&sem_w);}return NULL;
}void *do_world(void *arg)
{while(1) {sem_wait(&sem_w);printf("world\n");sem_post(&sem_h);}return NULL;}
typedef void *(*threadF_t)(void *);
int main(int argc, const char *argv[])
{int i;pthread_t tid[i];threadF_t pFunc[2] = {do_hello,do_world};sem_init(&sem_h,0,1);sem_init(&sem_w,0,0);for(i = 0;i < 2;++i){int ret = pthread_create(&tid[i],NULL,pFunc[i],NULL);if(ret != 0){errno = ret;perror("pthread_create fail");exit(EXIT_FAILURE);}}sem_destroy(&sem_h);sem_destroy(&sem_w);pthread_detach(tid[0]);pthread_detach(tid[1]);printf("---main----exit\n");pthread_exit(NULL);return 0;
}
进程间的通信方式:

三大类:
1.同主机 ---- 基于内存的
古老的通信方式
//管道 ----
无名管道
有名管道
//信号
IPC对象通信(改进)
消息队列(用的相对少,这里不讨论)
共享内存(*) //最高效
信号量集() //信号量
2.
//不同主机 、多台主机
socket //网络部分
//同一主机
2.1、古老的通信方式
管道:
无名管道
有名管道
信号
2.2、IPC对象通信 system v BSD suse fedora kernel.org
消息队列(用的相对少,这里不讨论)
共享内存(*) //最高效
信号量集() //信号量
//不同主机
3、socket通信
网络通信
1、pipe 无名管道
使用框架:
创建管道 ==》读写管道 ==》关闭管道
1、无名管道 ===》管道的特例 ===>pipe函数
特性:
1.1 亲缘关系进程使用
1.2 有固定的读写端
流程:
创建并打开管道: pipe函数
函数:
#include <unistd.h>
int pipe(int pipefd[2]);
int pipe(int *pipefd);
int fd[2];
功能:创建并打开一个无名管道
参数: @pipefd[0] ==>无名管道的固定读端//0 -- 标准输入
@pipefd[1] ==>无名管道的固定写端//1 -- 标准输出
返回值: 成功 0
失败 -1;
注意事项:
1、无名管道的架设应该在fork之前进行。
关闭管道: close();
练习:父进程输入、子进程打印
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include <sys/wait.h>int main(int argc, const char *argv[])
{int fd[2];if(pipe(fd) < 0){perror("pipe fail");return -1;}char buf[100] = {0};int ret = 0;pid_t pid = fork();while(1){if(pid < 0){perror("fork fail");return -1;}else if(pid > 0){close(fd[0]);printf(">");fflush(stdout);ret = read(0,buf,sizeof(buf));buf[ret] = '\0';write(fd[1],buf,strlen(buf) + 1);if(strncmp(buf,"quit",4) == 0){wait(NULL);close(fd[1]);return 0;}}else if(pid == 0){close(fd[1]);ret = read(fd[0],buf,sizeof(buf));printf("date = %s\n",buf);if(strncmp(buf,"quit",4) == 0){close(fd[0]);exit(0);}}}return 0;
}
管道的读写规则:
1.读端存在,写管道
管道空:可以写数据
管道满:会造成-->写阻塞
2.读端不存在,写管道
系统会给进程发一个信号SIGPIPE(管道破裂)
3.写端存在,读管道
管道空,读不到数据,
这时会造成读操作阻塞
4.写端不存在,读管道
如果管道中有数据,则读取这些数据!
如果没有数据,读操作不阻塞,立即返回!
2、fifo有名管道
有名管道===》fifo ==》有文件名称的管道。
文件系统中可见

框架:
(1).创建有名管道 -- 类似 文件 (管道文件)
(2).打开有名管道 -- open
(3).读写管道 -- read/write
(4).关闭管道 ==》卸载有名管道 //close
1、创建:mkfifo //创建了一个有名管道
#include <sys/types.h>
#include <sys/stat.h>
remove();
int mkfifo(const char *pathname, mode_t mode);
功能:
在指定的pathname路径+名称下创建一个权限为
mode的有名管道文件。
参数:@pathname要创建的有名管道路径+名称
mode 8进制文件权限。
返回值: 成功 0
失败 -1;
2、打开有名管道 open
注意:该函数使用的时候要注意打开方式,
因为管道是半双工模式,所有打开方式直接决定

当前进程的读写方式。
一般只有如下方式:
int fd-read = open("./fifo",O_RDONLY); ==>fd 是固定读端 //阻塞,只有双方以对应的方式打开的时候才会
int fd-write = open("./fifo",O_WRONLY); ==>fd 是固定写端
不能是 O_RDWR 方式打开文件。
不能有 O_CREAT 选项,因为创建管道有指定的mkfifo函数
有名管道打开:
注意,
如果一端是以只读,或者只写方式打开的。
程序会阻塞,
阻塞在打开操作。
直到另一端,以只写或只读方式打开。
A.c --- 只读
B.c --- 只写
练习:实现双向通信:
打开两个有名通道文件

// a
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>int main(int argc, const char *argv[])
{if (mkfifo("a_2_b",0666) < 0 && errno != EEXIST){perror("mkfifo fail");return -1;}if (mkfifo("b_2_a",0666) < 0 && errno != EEXIST){perror("mkfifo fail");return -1;}int fd_w = open("a_2_b",O_WRONLY);if (fd_w< 0){perror("open fail");return -1;}int fd_r = open("b_2_a",O_RDONLY);if (fd_r< 0){perror("open fail");return -1;}pid_t pid = fork();if (pid < 0){perror("fork fail");return -1;}char buf[1024] = {0};if (pid > 0){while (1){printf(">");fflush(stdout);fgets(buf,sizeof(buf),stdin);write(fd_w,buf,strlen(buf)+1);if (strncmp(buf,"quit",4) == 0){close(fd_w);close(fd_r);}}}else if (pid == 0){while (1){printf("<");int ret = read(fd_r,buf,sizeof(buf));printf("ret = %d: %s\n",ret,buf);}}return 0;
}// b
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>int main(int argc, const char *argv[])
{if (mkfifo("a_2_b",0666) < 0 && errno != EEXIST){perror("mkfifo fail");return -1;}if (mkfifo("b_2_a",0666) < 0 && errno != EEXIST){perror("mkfifo fail");return -1;}int fd_r = open("a_2_b",O_RDONLY);if (fd_r< 0){perror("open fail");return -1;}int fd_w = open("b_2_a",O_WRONLY);if (fd_w< 0){perror("open fail");return -1;}pid_t pid = fork();if (pid < 0){perror("fork fail");return -1;}char buf[1024] = {0};if (pid > 0){while (1){printf(">");fflush(stdout);fgets(buf,sizeof(buf),stdin);write(fd_w,buf,strlen(buf)+1);}}else if (pid == 0){while (1){printf("<");int ret = read(fd_r,buf,sizeof(buf));printf("ret = %d: %s\n",ret,buf);if (strncmp(buf,"quit",4) == 0){close(fd_w);close(fd_r);}}}return 0;
}
相关文章:
linux高级编程:线程(二)、进程间的通信方式
线程: 回顾线程(一): 1.线程间通信问题 线程间共享同一个资源(临界资源) 互斥: 排他性访问 linux系统 -- 提供了Posix标准的函数库 -- 互斥量(互斥锁) 原子操作&#x…...
Unity 佳能SDK 及数据获取
1. 填写信息跟官方申请SDK,大概1-2个工作日会邮件回复你 佳能(中国)- 佳定制(佳能影像产品),SDK,EDSDK,CCAPI,软件开发包下载 2. 将SDK这两个文件放到 Unity Plugins文件夹 3. 把CameraControl 下面只要是绿色的 .cs 文件都复制到Unity 中...
Unity(第二十三部)导航
你可以使用 unity官方提供的 unity导航组件或第三方 unity导航组件,以实现游戏中角色或其他物体的导航。 unity导航组件通常具有多种导航模式,如飞行模式、步行模式、车辆模式等,可以根据不同的需求选择合适的模式。同时,unity导…...
根据建表sql语句生成go的struct代码工具
sql2struct 一个根据"CREATE TABLE"建表语句生成对应的Go语言结构体的工具,暂只支持 MySQL 表。 开发目的 在 github 中找到一些 sql2struct,但要么是 chrome 插件,要么是在线工具,要么是需要连接 MySQL,…...
Qt 自定义长条进度条(类似播放器进度条)
1.运行界面 2.步骤 其实很简单。 2.1绘制底图圆角矩形 2.2绘制播放进度圆角矩形 参考:painter绘图 3.源码 #pragma once#include <QWidget> #include <QLabel> #include <QHBoxLayout> #include <QMouseEvent> #include <QDebug&g…...
休息日的思考与额外题——双指针、原地哈希day28
文章目录 前言一、11. 盛最多水的容器二、41. 缺失的第一个正数三、42. 接雨水总结 前言 一个本硕双非的小菜鸡,备战24年秋招,计划二刷完卡子哥的刷题计划,加油! 二刷决定精刷了,于是参加了卡子哥的刷题班,…...
数据修改
Oracle 目录 数据修改 将员工编号的 7369 的员工工资修改为 810,佣金改为 100 将工资最低的员工工资修改为公司的平均工资 将所有在 1981 年雇佣的员工的雇佣日期修改为今天,工资增长 20% 数据的更新操作 Oracle从入门到总裁:https://blog.csdn.n…...
Android JNI复杂用法,回调,C++中调用Java方法
Android JNI复杂用法,回调,C中调用Java方法 一、前言 Android JNI的 普通用法估计很多人都会,但是C中调用Java方法很多人不熟悉,并且网上很多介绍都是片段的。 虽然C/C调用Java不常用,但是掌握多一点还是有好处的。…...
C++从零开始的打怪升级之路(day41)
这是关于一个普通双非本科大一学生的C的学习记录贴 在此前,我学了一点点C语言还有简单的数据结构,如果有小伙伴想和我一起学习的,可以私信我交流分享学习资料 那么开启正题 今天分享的是关于继承的知识点 1.派生类的默认成员函数 首先我…...
uni-app app实现web-view H5图片长按下载
问题和使用场景描述: uniapp app web-view中图片无法长按保存,IOS下是正常的,但是Android下长按无反应 解决方案: 下载mui.min.js,放到项目中的static下(下载见最上面的压缩包) 在static目录下新建script.js mui.…...
全量知识系统问题及SmartChat给出的答复 之5
Q15. 支持前端(知识表征)的自然语言能力 需要一个 元语言注释工具 以及两个库(叙词库和语料库)和主题词表。请 1)设计 两个库和主题词表的结构 ,2)分别设计它们的接口,3)通过调用它们…...
DolphinScheduler——工作流实例的生命周期
目录 一、DolphinScheduler架构原理 1.1 系统架构图 1.2 DolphinScheduler核心概念 1.2 创建工作流 1.2.1 如何触发一个工作流实例 1.2.2 任务调度链路监控 1.2.3 Workflow-DAG解析 DAG解析 Dispatch分发流程 Master和Worker的交互过程 1.3 任务运行状态 该篇文章主…...
阻塞和非阻塞网络io有什么区别,分别有哪些应用场景?
阻塞(Blocking)和非阻塞(Non-blocking)网络I/O是两种不同的I/O模型,它们在处理I/O操作时的行为和特点有所不同。 阻塞式网络I/O(Blocking I/O): 在阻塞式网络I/O中,当应…...
面试数据库篇(mysql)- 12分库分表
拆分策略 垂直分库 垂直分库:以表为依据,根据业务将不同表拆分到不同库中。 特点: 按业务对数据分级管理、维护、监控、扩展在高并发下,提高磁盘IO和数据量连接数垂直分表:以字段为依据,根据字段属性将不同字段拆分到不同表中。 特点: 1,冷热数据分离 2,减少IO过渡争…...
LaTeX中的多行数学公式
目录 参考链接 一、gather以及gather*环境编排公式 1、 gather环境 2、 gather*环境 3、 阻止编号 二、align以及align*环境设定公式对齐方式 1、align环境 2、align*环境 三、split环境实现一个公式多行排版 四、cases环境实现分段函数 参考链接 LaTeX中的多行数学…...
绕过5秒盾Cloudflare和DDoS-GUARD
绕过5秒盾Cloudflare和DDoS-GUARD 5秒盾的特点免费版5秒盾的绕过方法付费版5秒盾的绕过方法 5秒盾的特点 <title>Just a moment...</title>例如: <!DOCTYPE html><html lang"en-US"><head><title>Just a moment...</title&…...
react 原理揭秘
1.目标 A. 能够知道setState()更新数据是异步的 B. 能够知道JSX语法的转化过程 C. 能够说出React组件的更新机制 D. 能够对组件进行性能优化 E. 能够说出虚拟DOM和Diff算法 2.目录 A. setState()的说明 B. JSX语法的转化过程 C. 组件更新机制 D. 组件性能优化 E. 虚拟DOM和D…...
el-table实现转置表格
vue版本:vue2.6.10 elementui版本:2.15.14 实现效果:el-table实现行列互换 代码: <template><div class"app-container"><span>原始数据</span><el-table:data"datas"border>…...
(3)(3.1) FlightDeck FrSky发射器应用程序
文章目录 前言 1 概述 2 Turnkey Packages 3 参数说明 前言 Craft and Theory 的 FlightDeck 可让你轻松查看飞行模式、高度、速度、姿态和关键系统警报,包括故障保护和电池错误,如电池不平衡警告和发射机低电量警报。 1 概述 Craft and Theory 的…...
【Unity】导入IAP插件后依赖冲突问题 com.android.billingclient冲突
【Unity】Attribute meta-data#com.google.android.play.billingclient.version 多版本库冲突_unity billingclient-CSDN博客 打开mainTemplate.gradle 找到dependencies { } 在里面末尾加上如下: configurations.all {exclude group: com.android.billingclien…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
