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

【Linux】进程等待

文章目录

  • 进程等待
    • 进程等待必要性
    • 实验(见见猪跑)
    • 进程等待的方法
      • wait方法
      • waitpid**方法**
      • 宏的使用方法
      • 获取子进程status
    • 阻塞VS非阻塞
      • 概念对比
      • 非阻塞有什么好处
  • 具体代码实现
    • 进程的阻塞等待方式:
    • 进程的非阻塞等待方式:
    • 让父进程做其他任务

进程等待

进程等待必要性

  • 之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。
  • 另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。
  • 最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。
  • 父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息
    因此,进程等待是为了:
  1. 避免内存泄漏
  2. 获取子进程执行的结果
    1. 代码跑完,结果对->退出码
    2. 代码跑完,结果不对->退出码
    3. 代码运行异常->信号

等待就是通过系统调用,获取子进程退出码或者退出信号的方式,顺便释放内存

实验(见见猪跑)

#include<sys/types.h>  
#include<sys/wait.h>  
int main()
{pid_t id = fork();if(id == 0){int cnt = 10;while(cnt){printf("我是子进程:%d,父进程:%d,cnt:%d\n",getpid(),getppid(),cnt--);}exit(10);//此时都是S状态}//此时子进程变成Z状态sleep(15);pid_t ret = wait(NULL);//回收子进程if(id > 0){printf("wait success:%d\n",ret);}sleep(5);//父进程退出
}

waitpid用法;

#include<sys/types.h>  
#include<sys/wait.h>  
int main()
{pid_t id = fork();if(id == 0)//子进程返回0,父进程返回子进程id{int cnt = 10;while(cnt){printf("我是子进程:%d,父进程:%d,cnt:%d\n",getpid(),getppid(),cnt--);}exit(10);//退出的三种结果://1.代码跑完,结果是对的//2.代码跑完,结果是错的//3.代码没有跑完,出异常了//此时都是S状态}//此时子进程变成Z状态sleep(15);int status = 0;pid_t ret = waitpid(id,&status,0);//回收子进程//错误观念:此时status的值变成了10//因为status不是被整体使用的,有自己的位图结构if(id > 0){printf("wait success:%d,sig number:%d,child exit code:%d\n",ret,(status & 0x7F,(status>>8)&0xFF);}//sig number:0 child exit code:10sleep(5);//父进程退出
}

监控脚本:

ps ajx | head -1 && ps axj | grep mytest | grep -v grep
第一句话是把标题拿出来
第二句话是把matest的进程信息拿出来
第三句话是把grep本身的进程信息去掉
之后写一个循环语句
while :; do ps ajx | head -1 && ps axj | grep mytest | grep -v grep; sleep 1; done

![[Pasted image 20221212134644.png]]
(ctrl + z 退出)

进程等待的方法

wait方法

:!man 2 wait //可以查看到相关wait的用法信息
需要包含两个头文件:
#include<sys/types.h>  
#include<sys/wait.h>  
pid_t wait(int* status);  
返回值:  
成功返回被等待进程pid,失败返回-1。  
参数:  
输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

waitpid方法

pid_ t waitpid(pid_t pid, int *status, int options);  
返回值:  
当正常返回的时候waitpid返回收集到的子进程的进程ID;  
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;  
如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;  
参数:  pid:  Pid=-1,等待任一个子进程。与wait等效。  Pid>0.等待其进程ID与pid相等的子进程。  status:  WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)  WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)  options:  WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。

这里有一个问题:
status按理来说是会返回信号+退出码的,但是一个整数怎么能返回两个整数呢?
所以我们不应该吧status当作一个完整的整数,而是应该看作位图结构(后面会详解)

宏的使用方法

int ret = waitpid(id,&status,0)
if(ret > 0)
{//是否正常退出if(WIFEXITED(status)){//判断子进程运行结果是否OKprintf("exit code :%d\n",WEXITSTATUS(status));}else//出异常了(比如kill -9){//TODOprintf("child exit not normal\n");}
}
  • 如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。
  • 如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。
  • 如果不存在该子进程,则立即出错返回。
    ![[Pasted image 20221112090227.png]]

获取子进程status

wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。
如果传递NULL,表示不关心子进程的退出状态信息。
否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。
status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图(本身是32位,但是这里我们只研究status低16比特位):

1.代码跑完,结果是对的
2.代码跑完,结果是错的
3.代码没有跑完,出异常了

终止信号(即退出码)用来表示是否正常结束(为0则表示正常退出)
用退出状态表示结果是否正确(通过kill -l进行对应数字的查看(比如发生段错误,除0操作等)),此时退出码是否为0或者是其他的,都无意义,我们不讨论它.
第七位是信号编号
![[Pasted image 20221112090250.png]]

获取退出状态:
(status>>8)&0xFF )
获取终止信号:
``(status & 0x7F))

#include<sys/types.h>
#include<stdio.h>
#include<sys/wait.h>  
int main()
{pid_t id = fork();if (id == 0){int cnt = 10;while (cnt){printf("我是子进程:%d,父进程:%d,cnt:%d\n", getpid(), getppid(), cnt--);sleep(1);}}int status = 0;//1.让OS释放子进程的僵尸状态//2.获取子进程的退出结果//3.在等待期间,子进程没有退出的时候,父进程只能阻塞等待.pid_t ret = waitpid(id, &status, 0);if (id > 0){printf("wait success: %d,sig number : %d ,child exit code: %d\n",ret,(status & 0x7F),(status>>8)&0xFF );}}
测试代码:  
#include <sys/wait.h>  
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <errno.h>  
int main( void )
{  pid_t pid;  if ( (pid=fork()) == -1 )  perror("fork"),exit(1);  if ( pid == 0 ){  sleep(20);  exit(10);  } else {  int st;  int ret = wait(&st);  if ( ret > 0 && ( st & 0X7F ) == 0 ){ // 正常退出  printf("child exit code:%d\n", (st>>8)&0XFF);  } else if( ret > 0 ) { // 异常退出  printf("sig code : %d\n", st&0X7F );  }  }  
}  
测试结果:  [root@localhost linux]# ./a.out #等20秒退出  child exit code:10  [root@localhost linux]# ./a.out #在其他终端kill掉  sig code : 9

等待的本质:
监测子进程退出的信息
并且将子进程退出信息通过status拿回来
这个信息(exit code ,signal)在子进程的PCB中

![[进程控制 2022-12-12 14.39.31.excalidraw]]

再谈进程退出:
1.进程退出会变成僵尸进程->会把自己的退出结果写到自己的task_struct
2.wait/waitpid是一个系统调用->OS->OS有资格也有能力去读取子进程的task_struct

阻塞VS非阻塞

概念对比

例子:

1.不挂电话,监测李四的状态->阻塞
2.张三->李四,本质是状态检测,如果没有就绪,直接返回->每一次都是一次非阻塞等待->多次非阻塞等待我们称为:轮询

打电话->系统调用wait/waitpid
张三->父进程
李四->子进程
我们上面写的代码都是阻塞等待
轮询等待:

#include<sys/types.h>
#include<stdio.h>
#include<sys/wait.h>  
int main()
{pid_t id = fork();if (id == 0){int cnt = 10;while (cnt){printf("我是子进程:%d,父进程:%d,cnt:%d\n", getpid(), getppid(), cnt--);sleep(1);}}int status = 0;while(1)//这是一个死循环,作为轮询等待的一个条件!{pid_t ret = waitpid(id, &status, WNOHANG);//wnohang:非阻塞:子进程没有退出时,父进程监测之后立即返回//如果没有设置WNOHANG,则会卡在这一步,除非子进程退出,或者你的id值设置得有问题.否则不会执行下面的代码if(ret == 0)//设置了WNOHANG才会可能出现返回值为0的情况{//waitpid调用成功&&子进程没有退出,我的waitpid没有等待失败//仅仅是监测到了子进程没有退出printf("wait done,but child is running\n",);}else if(ret > 0){//1.waitpid调用成功(等待成功)&&子进程退出了		printf("wait success: %d,sig number : %d ,child exit code: %d\n",ret,(status & 0x7F),(status>>8)&0xFF );break;}else{//waitpid调用失败,返回值为-1//eg.传入的id参数传错了printf("waitpid call failed\n");break;}sleep(1);}
}

非阻塞有什么好处

不会占用父进程的所有精力,可以在轮询期间干干其他的
[[指针进阶]]
[[typedef函数进阶]]

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <assert.h>
#include <stdlib.h>#define TASK_NUM 10typedef void (*func_t)();
func_t other_task[TASK_NUM] = {NULL};void sync_disk()
{printf("这是一个刷新磁盘的任务\n");
}
void sync_log()
{printf("这是一个同步日志的任务\n");
}
void net_send()
{printf("这是一个网络发送的任务\n");
}void LoadTask(func_t func)
{for (int i = 0; i < TASK_NUM; i++){if (other_task[i] == NULL){other_task[i] = func;break;}}
}void InitTask()
{for (int i = 0; i < TASK_NUM; i++)other_task[i] = NULL;LoadTask(sync_disk);LoadTask(sync_log);LoadTask(net_send);
}void RunTask()
{for (int i = 0; i < TASK_NUM; i++){if (other_task[i] == NULL)continue;other_task[i]();}
}int main()
{pid_t id = fork();assert(id >= 0);if (id == 0){int cnt = 5;while (cnt){printf("我是子进程,我的pid是:%d,我的ppid是%d,我还有%dS存活\n", getpid(), getppid(), cnt--);sleep(1);}printf("我已经退出\n");exit(11);}InitTask();while (1){sleep(1);int status;pid_t ret_id = waitpid(id, &status, WNOHANG);if (ret_id > 0){printf("我是父进程,我已经回收子进程,ret_id是%d,退出码为%d,退出信号为%d\n", ret_id, (status >> 8) & 0xFF, status & 0x7F);exit(0);}else if (ret_id == 0){RunTask();continue;}else{printf("调用出错\n");}}
}

具体代码实现

进程的阻塞等待方式:

#define _CRT_SECURE_NO_WARNINGS 1
int main()
{pid_t pid;pid = fork();if (pid < 0) {printf("%s fork error\n", __FUNCTION__);return 1;}else if (pid == 0) { //childprintf("child is run, pid is : %d\n", getpid());sleep(5);exit(257);}else {int status = 0;pid_t ret = waitpid(-1, &status, 0);//阻塞式等待,等待5Sprintf("this is test for wait\n");if (WIFEXITED(status) && ret == pid) {printf("wait child 5s success, child return code is :%d.\n", WEXITSTATUS(status));}else {printf("wait child failed, return.\n");return 1;}}return 0;
}
运行结果:
[root@localhost linux] # . / a.out
child is run, pid is : 45110
this is test for wait
wait child 5s success, child return code is : 1.

进程的非阻塞等待方式:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{pid_t pid;pid = fork();if (pid < 0) {printf("%s fork error\n", __FUNCTION__);return 1;}else if (pid == 0) { //childprintf("child is run, pid is : %d\n", getpid());sleep(5);exit(1);}else {int status = 0;pid_t ret = 0;do{ret = waitpid(-1, &status, WNOHANG);//非阻塞式等待->子进程没有退出,父进程检测时候,立即返回if (ret == 0) {//子进程没有退出,我的waitpid没有等待失败//仅仅是监测到了子进程没有退出printf("child is running\n");}sleep(1);} while (ret == 0);if (WIFEXITED(status) && ret == pid) {printf("wait child 5s success, child return code is :%d.\n", WEXITSTATUS(status));}else {printf("wait child failed, return.\n");return 1;}}return 0;
}

让父进程做其他任务

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>#define TASK_NUM 10// 要保存的任务相关的
typedef void (*func_t)(); //?
func_t other_task[TASK_NUM] = {NULL};  //函数指针数组// 预设一批任务
void sync_disk()
{printf("这是一个刷新数据的任务!\n");
}
void sync_log()
{printf("这是一个同步日志的任务!\n");
}
void net_send()
{printf("这是一个进行网络发送的任务!\n");
}//将任务加载进任务列表
int LoadTask(func_t func)
{int i = 0;for(; i < TASK_NUM; i++){if(other_task[i] == NULL) break;}if(i == TASK_NUM) return -1;else other_task[i] = func;return 0;
}void InitTask()
{for(int i = 0; i < TASK_NUM; i++) other_task[i] = NULL;LoadTask(sync_disk);LoadTask(sync_log);LoadTask(net_send);
}void RunTask()
{for(int i = 0; i < TASK_NUM; i++){if(other_task[i] == NULL) continue;other_task[i]();}
}int main()
{pid_t id = fork();if(id == 0){//子进程int cnt = 50;while(cnt){printf("我是子进程,我还活着呢,我还有%dS, pid: %d, ppid%d\n", cnt--, getpid(), getppid());sleep(1);//int *p = NULL;//*p = 100;}exit(111);}InitTask();// 父进程//pid_t ret_id = wait(NULL);while(1){int status = 0;pid_t ret_id = waitpid(id, &status, WNOHANG); // 夯住了if(ret_id < 0){printf("waitpid error!\n");exit(1);}else if(ret_id == 0){RunTask();sleep(1);continue;}else{if(WIFEXITED(status)) // 是否收到信号{printf("wait success, child exit code: %d\n", WEXITSTATUS(status));}else{printf("wait success, child exit signal: %d\n", status & 0x7F);}// printf("我是父进程,等待子进程成功, pid: %d, ppid: %d, ret_id: %d, child exit code: %d, child exit signal: %d\n",\//     getpid(), getppid(), ret_id, (status>>8)&0xFF, status & 0x7F);break;}}

相关文章:

【Linux】进程等待

文章目录 进程等待进程等待必要性实验(见见猪跑)进程等待的方法wait方法waitpid**方法**宏的使用方法获取子进程status 阻塞VS非阻塞概念对比非阻塞有什么好处 具体代码实现进程的阻塞等待方式:进程的非阻塞等待方式:让父进程做其他任务 进程等待 进程等待必要性 之前讲过&am…...

电视「沉浮录」:跌出家电“三大件”?

【潮汐商业评论/原创】 “这年头谁还看电视&#xff0c;家里电视近一年都没打开过了&#xff0c;我明天就打算把它二手卖掉。”想到已落灰许久的电视机&#xff0c;Andy打开了二手平台。 “要不是这几年孩子网课多&#xff0c;我是真没考虑换新电视&#xff0c;家里用了8年的…...

前端实现调用打印机和小票打印(TSPL )功能

Ⅰ- 壹 - 使用需求 前端 的方式 点击这个按钮&#xff0c;直接让打印机打印我想要的东西 Ⅱ - 贰 - 小票打印 目前比较好的方式就是直接用 TSPL 标签打印指令集, 基础环境就不多说了,这个功能的实现就是利用usb发送指令,现在缺少个来让我们能够和usb沟通的工具,下面这就是推…...

串口通信(6)应用定时器中断+串口中断实现接收一串数据

本文为博主 日月同辉&#xff0c;与我共生&#xff0c;csdn原创首发。希望看完后能对你有所帮助&#xff0c;不足之处请指正&#xff01;一起交流学习&#xff0c;共同进步&#xff01; > 发布人&#xff1a;日月同辉,与我共生_单片机-CSDN博客 > 欢迎你为独创博主日月同…...

【WinForm详细教程六】WinForm中的GroupBox和Panel 、TabControl 、SplitContainer控件

文章目录 1.GroupBox和Panel2.TabControl3.SplitContainer 1.GroupBox和Panel GroupBox&#xff1a;是一个分组容器&#xff0c;提供一个框架将相关的控件组织在一起&#xff0c;它有标题、边框&#xff0c;但没有滚动条。 Panel&#xff1a;也是一个容器控件&#xff0c;用来…...

gradle与maven

Gradle 和 Maven 都是流行的构建工具&#xff0c;通常用于构建和管理 Java 和 Android 项目。它们都可以自动下载依赖库、编译代码、运行测试、打包和发布等。 以下是对 Gradle 和 Maven 的介绍&#xff1a; Gradle&#xff1a; Gradle 是一个基于 Groovy 和 Kotlin 的构建自…...

2.Docker基本架构简介与安装实战

1.认识Docker的基本架构 下面这张图是docker官网上的&#xff0c;介绍了整个Docker的基础架构&#xff0c;我们根据这张图来学习一下docker的涉及到的一些相关概念。 1.1 Docker的架构组成 Docker架构是由Client(客户端)、Docker Host(服务端)、Registry(远程仓库)组成。 …...

拓世法宝 | 数字经济崛起,美业如何抓住流量风口?

爱美之心&#xff0c;人皆有之。无论男女&#xff0c;都会很自然地对美好事物燃起兴致&#xff0c;跟高颜值相关的事物总能聚集注意力。例如直播平台里的美女网红收割流量赚得盆满钵满&#xff0c;面庞俊俏的年轻偶像吸引万千粉丝&#xff0c;还有“央视最美记者”王冰冰、“最…...

Scala 泛型编程

1. 泛型 Scala 支持类型参数化&#xff0c;使得我们能够编写泛型程序。 1.1 泛型类 Java 中使用 <> 符号来包含定义的类型参数&#xff0c;Scala 则使用 []。 class Pair[T, S](val first: T, val second: S) {override def toString: String first ":" sec…...

索引失效的场景有哪些?

虽然你这列上建了索引&#xff0c;查询条件也是索引列&#xff0c;但最终执行计划没有走它的索引。下面是引起这种问题的几个关键点。 列与列对比 某个表中&#xff0c;有两列&#xff08;id和c_id&#xff09;都建了单独索引&#xff0c;下面这种查询条件不会走索引 select…...

Java进阶04 final关键字、abstract抽象、interface接口、JDK8与JDK9中接口的区别、内部类和匿名类

文章目录 一、final关键字二、abstract关键字三、接口interface四、JDK8和JDK9中接口的区别五、内部类 一、final关键字 final可以修饰类、方法、变量 用final修饰类 表示此类不能被继承 用final修饰方法 表示方法不可以被重写 用final修饰变量 既可以修饰成员变量也可以修饰…...

Python的web自动化学习(五)Selenium的隐式等待(元素定位)

引言&#xff1a; WebDriver隐式等待是一种全局性的等待方式&#xff0c;它会在查找元素时设置一个固定的等待时间。当使用隐式等待时&#xff0c;WebDriver会在查找元素时等待一段时间&#xff0c;如果在等待时间内找到了元素&#xff0c;则立即执行下一步操作&#xff1b;如果…...

20231102从头开始配置cv180zb的编译环境(欢迎入坑,肯定还有很多问题等着你)

20231102从头开始配置cv180zb的编译环境&#xff08;欢迎入坑&#xff0c;肯定还有很多问题等着你&#xff09; 2023/11/2 11:31 &#xff08;欢迎入坑&#xff0c;本篇只是针对官方的文档整理的&#xff01;只装这些东西你肯定编译不过的&#xff0c;还有很多问题等着你呢&…...

CentOS 安装HTTP代理服务器 Squid

参考&#xff1a;大部分摘自此文&#xff0c;做了少部分修改 Squid 是一个功能全面的缓存代理服务器&#xff0c;它支持著名的网络协议像 HTTP&#xff0c;HTTPS&#xff0c;FTP 等等。将 Squid 放在网页服务器的前端&#xff0c;通过缓存重复请求&#xff0c;过滤网络流量等&…...

ubuntu下开发提效的小tips

一、常用操作使用简写的别名&#xff0c;写进bashrc文件中 背景&#xff1a;经常需要cd至某个文件夹中&#xff0c;然后再执行对应的操作&#xff1b;写进bashrc文件中后&#xff0c;可以直接用缩略命令替代这一连串的命令&#xff1b; 用到的工具&#xff1a; 设置命令别名a…...

Java反射详解:入门+使用+原理+应用场景

反射非常强大和有用&#xff0c;现在市面上绝大部分框架(spring、mybatis、rocketmq等等)中都有反射的影子&#xff0c;反射机制在框架设计中占有举足轻重的作用。 所以&#xff0c;在你Java进阶的道路上&#xff0c;你需要掌握好反射。 怎么才能学好反射&#xff0c;我们需要…...

PostgreSQL 工具的相关介绍

1.1 psql工具 psql是PostgreSQL中的一个命令行交互式客户端工具&#xff0c;类似 Oracle中的命令行工具sqlplus&#xff0c;它允许用户交互地键入SQL语句或命 令&#xff0c;然后将其发送给PostgreSQL服务器&#xff0c;再显示SQL语句或命令的结 果。 1.2 psql的简单使用 使用…...

结合组件库实现table组件树状数据的增删改

如图所示&#xff0c;可以实现树状数据的新增子项&#xff0c;新增平级&#xff0c;删除。主要用到了递归 代码&#xff1a; <template><el-table :data"tableData" style"width: 100%; margin-bottom: 20px" row-key"id" border def…...

Microsoft 365 管理自动化

Microsoft 365 服务被大多数组织广泛使用&#xff0c;每天生成的数据量巨大。解决 Microsoft 365 中的问题可能非常困难&#xff0c;并且使用多个管理中心来保护组织变得复杂。本机控制台还缺少某些批量管理任务、全面的审计报告和基于角色的精细访问控制。 Microsoft 360 管理…...

unraid 安装并设置 zerotier 内网穿透安装 unraid 局域网内其他设备

Read Original 最近看了以下两个文章&#xff0c;感谢发布的各种精彩文章&#xff0c;让我受益匪浅。OPENWRT 的固件在设置了&#xff0c;【自动允许客户端 NAT】后&#xff0c;可以直接访问局域网其他设备&#xff0c;而我 unraid 部署 zerotier 后&#xff0c;只能访问 unra…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...