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

【Linux】进程通信篇Ⅱ:共享内存、消息队列、信号量

文章目录

  • 一、共享内存
    • 1.1 一些接口
      • 1. shmget 函数:申请一个 system v 的共享内存块
      • 2. ftok 函数:设置唯一标识码
      • 3. shmctl 函数:控制 system v 的共享内存块(可以删除、查看...)
      • 4. shmat 函数:将进程与共享内存块 关联\ 挂接(attach)
      • 5. shmdt 函数:将进程与共享内存块 去关联(detach)
    • 1.2 一些命令
      • 1. ipcs - - 查看三种 ipc 资源
      • 2. ipcrm -- 删除某种 ipc 资源
    • 1.3 结论
  • 二、消息队列
      • 1. msgget 函数:创建消息队列
      • 2. msgctl 函数
      • 3. msgsnd 和 msgrcv 函数,发送和接收消息
  • 三、信号量
      • 1. semget
      • 2. semctl 函数:可以获取信号量的相关属性
      • 3. semop 函数:对信号量进行操作
  • 总结:


一、共享内存

我们知道,进程间通信的本质就是:让不同的进程,看到同一份资源

这里要介绍的同一份资源就是:内存块,即 共享内存(shared memory,简写为 shm)

共享内存的原理:
1.创建(key 和 共享内存)
2.关联进程 和 取消关联
3.释放共享内存

内存中的每块共享内存,会有一个 struct shm 结构体,里面放着共享内存的全部属性,OS 通过这个结构体建立链表关系来对所有的共享内存进行管理,就等于把管理 shm 的问题转化成了管理链表的问题。

故:

共享内存
=
共享内存的内核数据结构 (伪代码:struct shm)
+
真正开辟的内存空间

1.1 一些接口

1. shmget 函数:申请一个 system v 的共享内存块

头文件:

#include <sys/ipc.h>
#include <sys/shm.h>// umask的头文件如下
#include <sys/types.h>
#include <sys/stat.h>

int shmget(key_t key, size_t size, int shmflg);

参数 key:

  • 使用 ftok 函数设置的唯一标识码,他虽由用户设置,却是在内核中使用的


参数 size

  • 需要申请共享内存块的大小,单位为字节,不足 PAGE 页(4KB)时,会向上对齐到 PAGE 页


参数 shmflg:

  • 选项 IPC_CREAT and IPC_EXCL

  • 单独使用 IPC_CREAT:创建一个共享内存,如果共享内存不存在,就创建,如果已经存在就获取已经存在的共享内存并返回。

  • IPC_CREAT | IPC_EXCL :IPC_EXCL 必须要配合 IPC_CREAT 使用,创建一个共享内存,如果共享内存不存在,就创建,如果已经存在就出错返回
    意味着,一起使用时,如果创建成功,对应的shm,一定是最新的!

  • IPC_CREAT | IPC_EXCL | 0666 :上面的基础上,添加权限(可以配合函数 umask(0) 使用)


返回值:

  • 成功会返回一个共享内存标识符,失败返回 -1

2. ftok 函数:设置唯一标识码

头文件

#include <sys/types.h>
#include <sys/ipc.h>

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

参数 pathname

  • 用户设置的路径


参数 proj_id

  • 用户设置的项目 id


返回值:

  • 根据用户传入的参数,结合一定的算法,返回一个冲突概率很低的值。ket_t 就是一个 32 位的整数,是对 int 的封装

3. shmctl 函数:控制 system v 的共享内存块(可以删除、查看…)

头文件

#include <sys/ipc.h>
#include <sys/shm.h>   

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

参数 shmid

  • 需要的共享内存块的 shmid


参数 cmd:

  • 选项 IPC_STAT:把用户传入 shmid 的相应内核数据结构信息复制到 buf 中(在调用者有读权限的情况下,才能成功
  • 选项 IPC_RMID:删除 shmid 为传入值的共享内存块


输出型参数 buf:

  • 需要得到 ipc 信息时传一个相应类型的值用来接收结果


返回值:

  • 失败返回 -1,成功则根据 cmd 传入的选项返回对应的值
//The buf argument is a pointer to a shmid_ds structure, defined in <sys/shm.h> as follows:struct shmid_ds {struct ipc_perm shm_perm;    /* Ownership and permissions */size_t          shm_segsz;   /* Size of segment (bytes) */time_t          shm_atime;   /* Last attach time */time_t          shm_dtime;   /* Last detach time */time_t          shm_ctime;   /* Last change time */pid_t           shm_cpid;    /* PID of creator */pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */shmatt_t        shm_nattch;  /* No. of current attaches */...};//The ipc_perm structure is defined as follows (the highlighted fields  are  settable  using IPC_SET):struct ipc_perm {key_t          __key;    /* Key supplied to shmget(2) */uid_t          uid;      /* Effective UID of owner */gid_t          gid;      /* Effective GID of owner */uid_t          cuid;     /* Effective UID of creator */gid_t          cgid;     /* Effective GID of creator */unsigned short mode;     /* Permissions + SHM_DEST andSHM_LOCKED flags */unsigned short __seq;    /* Sequence number */};

4. shmat 函数:将进程与共享内存块 关联\ 挂接(attach)

头文件

#include <sys/types.h>
#include <sys/shm.h>

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

参数 shmid

  • 需要的共享内存块的 shmid


参数 shmaddr:

  • 用户可以选择虚拟地址作为共享内存块的起始地址
  • 用户一般不定义,设为 nullptr 让 OS 自主定义即可


参数 shmflg:

  • 选项 SHM_RDONLY:只读
  • 0:可以读写


返回值:

  • 挂接成功,返回共享内存块的虚拟地址的起始地址

5. shmdt 函数:将进程与共享内存块 去关联(detach)

头文件

#include <sys/types.h>
#include <sys/shm.h>

int shmdt(const void *shmaddr);

参数 shmaddr:

  • 共享内存块的起始地址


返回值:

  • 去关联成功返回 0,失败返回 -1

1.2 一些命令

1. ipcs - - 查看三种 ipc 资源

ipcs 就是进程间通信(ipc)资源

ipcs:可以查看 消息队列、共享内存亏块、信号量
-m:查看 共享内存块(memory)
-s:查看 信号量(semaphore)

perms:权限
nattach:当前 ipc 挂接的进程数

2. ipcrm – 删除某种 ipc 资源

ipcrm:删除一个 消息队列、共享内存亏块、信号量
-m:删除一个共享内存块,后接 shmid

1.3 结论

  1. 两个进程管道通信一次,需要进行两次复制。而共享内存间的通信,可以让进程们直接在自己映射的地址空间中访问,减少了拷贝次数()

  2. 管道单方面关闭读写端会有相应的保护,而共享内存没有保护机制(同步互斥)。管道通过系统接口通信,共享内存直接通信

  3. 互斥:任何一个时刻,都只允许一个执行流在进行共享资源的访问,叫做加锁

  4. 我们把任何一个时刻,都只允许一个执行流在进行访问的共享资源,叫做 临界资源。凡是访问临界资源的代码,叫做临界区,控制进出临界区的手段造就了临界资源。



二、消息队列

1. msgget 函数:创建消息队列

头文件

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg)

参数 key:

  • 使用 ftok 函数设置的唯一标识码


参数 msgflg:

  • 选项 IPC_CREAT and IPC_EXCL

  • 单独使用 IPC_CREAT:创建一个共享内存,如果共享内存不存在,就创建,如果已经存在就获取已经存在的共享内存并返回。

  • IPC_CREAT | IPC_EXCL :IPC_EXCL 必须要配合 IPC_CREAT 使用,创建一个共享内存,如果共享内存不存在,就创建,如果已经存在就出错返回
    意味着,一起使用时,如果创建成功,对应的shm,一定是最新的!

  • IPC_CREAT | IPC_EXCL | 0666 :上面的基础上,添加权限(可以配合函数 umask(0) 使用)


返回值:

  • 成功则返回消息队列的标识符

2. msgctl 函数

头文件

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

参数 msqid

  • 需要的消息队列的 msqid


参数 cmd:

  • 选项 IPC_STAT:把用户传入 msqid 的相应内核数据结构信息复制到 buf 中(在调用者有读权限的情况下,才能成功
  • 选项 IPC_RMID:删除 msqid 为传入值的共享内存块


输出型参数 buf:

  • 需要得到 ipc 信息时传一个相应类型的值用来接收结果


返回值:

  • 成功返回 >= 0 的值,失败返回 -1
The msqid_ds data structure is defined in <sys/msg.h> as follows:struct msqid_ds {struct ipc_perm msg_perm;     /* Ownership and permissions */time_t          msg_stime;    /* Time of last msgsnd(2) */time_t          msg_rtime;    /* Time of last msgrcv(2) */time_t          msg_ctime;    /* Time of last change */unsigned long   __msg_cbytes; /* Current number of bytes inqueue (nonstandard) */msgqnum_t       msg_qnum;     /* Current number of messagesin queue */msglen_t        msg_qbytes;   /* Maximum number of bytesallowed in queue */pid_t           msg_lspid;    /* PID of last msgsnd(2) */pid_t           msg_lrpid;    /* PID of last msgrcv(2) */};The ipc_perm structure is defined as follows (the highlighted fields  are  settable  using
IPC_SET):struct ipc_perm {key_t          __key;       /* Key supplied to msgget(2) */uid_t          uid;         /* Effective UID of owner */gid_t          gid;         /* Effective GID of owner */uid_t          cuid;        /* Effective UID of creator */gid_t          cgid;        /* Effective GID of creator */unsigned short mode;        /* Permissions */unsigned short __seq;       /* Sequence number */};

3. msgsnd 和 msgrcv 函数,发送和接收消息

头文件

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

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

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

参数 msqid:

  • 发送和接收访问的同一个消息队列

参数 msgp:

  • 发送或接收的数据块

参数 msgsz:

  • 发送或接收数据块的大小

参数 msgflg:

  • 选项,一般填 0 即可

参数 msgtyp:

  • msgbuf 里面的 mtype
// The msgp argument is a pointer to caller-defined structure of the following general form:struct msgbuf {long mtype;       /* message type, must be > 0 */char mtext[1];    /* message data */
};


三、信号量

信号量 / 信号灯(semaphore),本质 就是一个计数器,是一个描述资源数量的计数器

举个例子:

  • 比如我们任何一个执行流,像访问临界资源中的一个子资源的时候,不能直接访问,需要 先申请信号量资源(P操作),此时 count-- 。只要申请信号量成功,未来就一定能拿到一个子资源。(类似摇号)

  • 然后进入进程自己的临界区,访问对应的临界资源。

  • 使用完成后,进程释放信号量资源(V操作),只要将计数器增加 count++,就表示将我们对应的资源进行了归还。

至此,进程通过执行代码来申请,意味着,所有进程都得先看到信号量,信号量就是一个共享资源。(信号量保护共享资源,自己却又是一个共享资源)

故,信号量必须保证自己的 ++ - - 是原子的
也,信号量被归类到了进程间通信

信号量部分未完待续~

1. semget

头文件

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

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

参数 key:

  • 使用 ftok 函数设置的唯一标识码,他虽由用户设置,却是在内核中使用的


参数 nsems:

  • 申请信号量的个数(叫做信号量集)


参数 semflg:

  • 选项 IPC_CREAT and IPC_EXCL

  • 单独使用 IPC_CREAT:创建一个共享内存,如果共享内存不存在,就创建,如果已经存在就获取已经存在的共享内存并返回。

  • IPC_CREAT | IPC_EXCL :IPC_EXCL 必须要配合 IPC_CREAT 使用,创建一个共享内存,如果共享内存不存在,就创建,如果已经存在就出错返回
    意味着,一起使用时,如果创建成功,对应的shm,一定是最新的!

  • IPC_CREAT | IPC_EXCL | 0666 :上面的基础上,添加权限(可以配合函数 umask(0) 使用)


返回值:

  • 成功会返回一个信号量计数器标识符,失败返回 -1

2. semctl 函数:可以获取信号量的相关属性

头文件

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semctl(int semid, int semnum, int cmd, ...);

参数 semid:

  • 需要的信号量的semid


参数 semnum:

  • 信号量编号


参数 cmd:

  • 选项 IPC_STAT:把用户传入 msqid 的相应内核数据结构信息复制到 buf 中(在调用者有读权限的情况下,才能成功
  • 选项 IPC_RMID:删除 msqid 为传入值的共享内存块


返回值:

  • 成功返回 >= 0 的值,失败返回 -1
//This  function  has  three  or four arguments, depending on cmd.  When there are four, the
//fourth has the type union semun.  The calling program must define this union as follows:union semun {int              val;    /* Value for SETVAL */struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */unsigned short  *array;  /* Array for GETALL, SETALL */struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux-specific) */};//The semid_ds data structure is defined in <sys/sem.h> as follows:struct semid_ds {struct ipc_perm sem_perm;  /* Ownership and permissions */time_t          sem_otime; /* Last semop time */time_t          sem_ctime; /* Last change time */unsigned long   sem_nsems; /* No. of semaphores in set */};//The ipc_perm structure is defined as follows (the highlighted fields  are  settable  usingIPC_SET):struct ipc_perm {key_t          __key; /* Key supplied to semget(2) */uid_t          uid;   /* Effective UID of owner */gid_t          gid;   /* Effective GID of owner */uid_t          cuid;  /* Effective UID of creator */gid_t          cgid;  /* Effective GID of creator */unsigned short mode;  /* Permissions */unsigned short __seq; /* Sequence number */};

3. semop 函数:对信号量进行操作

头文件

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semop(int semid, struct sembuf *sops, unsigned nsops);

参数 sops:

  • 需要用户自己定义后传入,设置结构体内容,以此达到对信号量的 PV 操作等等
//Each semaphore in a System V semaphore set has the following associated values:unsigned short  semval;   /* semaphore value */unsigned short  semzcnt;  /* # waiting for zero */unsigned short  semncnt;  /* # waiting for increase */pid_t           sempid;   /* ID of process that did last op *///semop() performs operations on selected semaphores in the set indicated by semid.  
//Each of the nsops elements in the array pointed to by sops specifies an operation to be  performed on a single semaphore.  
//The elements of this structure are of type struct sembuf, containing the following members:unsigned short sem_num;  /* semaphore number */short          sem_op;   /* semaphore operation */short          sem_flg;  /* operation flags */

总结:

共享内存、消息队列、信号量 这三种 ipc 都有各自的内核数据结构体,而结构体的第一个成员都是 struct ipc_perm xx_perm

可以理解为 OS 将这三种 ipc 都放进了一个 struct ipc_perm* ipc_id_arr[] 指针数组中进行管理(这里只是做理解解释,实际上更复杂)。

OS 通过指针,可以找到每个结构体(同时也是每个结构的第一个成员,即 struct ipc_perm xx_perm),在其中找到 key 值就可以确定。

要访问里面的内容时,以共享内存举例

((struct shmid_ds*)ipc_id_arr[n])->other...

对指针进行强转,就可以访问到其中内容了,这也是一种多态。

相关文章:

【Linux】进程通信篇Ⅱ:共享内存、消息队列、信号量

文章目录 一、共享内存1.1 一些接口1. shmget 函数&#xff1a;申请一个 system v 的共享内存块2. ftok 函数&#xff1a;设置唯一标识码3. shmctl 函数&#xff1a;控制 system v 的共享内存块&#xff08;可以删除、查看...&#xff09;4. shmat 函数&#xff1a;将进程与共享…...

8.14 校招 内推 面经

绿泡泡&#xff1a; neituijunsir 交流裙&#xff0c;内推/实习/校招汇总表格 1、半导体芯片一周资讯 - 小米OPPO之后&#xff0c;星纪魅族调整芯片业务&#xff0c;今年应届生或被全部优化&#xff0c;英伟达2024推出比H100更快的芯片 半导体芯片一周资讯 - 小米OPPO之后&…...

阿里云服务器安装部署Docker使用教程

本文阿里云百科分享如何在云服务ECS实例上&#xff0c;部署并使用Docker。Docker是一款开源的应用容器引擎&#xff0c;具有可移植性、可扩展性、高安全性和可管理性等优势。开发者可将应用程序和依赖项打包到一个可移植的容器中&#xff0c;快速发布到Linux机器上并实现虚拟化…...

WebRTC | ICE详解

目录 一、Candidate种类与优先级 二、ICE策略 1. iceServers 2. iceTransportPolicy 三、P2P连接 1.Nat类型 &#xff08;1&#xff09;完全锥型NAT &#xff08;2&#xff09;IP限制锥型NAT &#xff08;3&#xff09;端口限制锥型NAT &#xff08;4&#xff09;对称…...

网络设备(防火墙、路由器、交换机)日志分析监控

外围网络设备&#xff08;如防火墙、路由器、交换机等&#xff09;是关键组件&#xff0c;因为它们控制进出公司网络的流量。因此&#xff0c;监视这些设备的活动有助于 IT 管理员解决操作问题&#xff0c;并保护网络免受攻击者的攻击。通过收集和分析这些设备的日志来监控这些…...

2023年国赛数学建模思路 - 复盘:人力资源安排的最优化模型

文章目录 0 赛题思路1 描述2 问题概括3 建模过程3.1 边界说明3.2 符号约定3.3 分析3.4 模型建立3.5 模型求解 4 模型评价与推广5 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 描述 …...

Compute shader SV 理解图

本图转子&#xff1a;【Computeshader】个人总结_蒋伟博的博客-CSDN博客...

生信豆芽菜-多种算法计算免疫浸润

网址&#xff1a;http://www.sxdyc.com/immuneInfiltration 一、使用方法 1、数据准备 一个全编码蛋白的表达谱基因&#xff0c;其中行为基因&#xff0c;列为样本 第一列为基因为行名&#xff0c;不能重复 2、选择计算的方法&#xff08;这里提供了5种免疫计算的方法&#x…...

逆向破解学习-单机斗地主

试玩 破解思路 9000 是成功的代码 Hook代码 import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class HookComJuneGameDouDiZhu extends HookImpl{ Override p…...

matplotlib绘制位置-时序甘特图

文章目录 1 前言2 知识点2.1 matplotlib.pyplot.barh2.2 matplotlib.legend的handles参数 3 代码实现4 绘制效果5 总结参考 1 前言 这篇文章的目的是&#xff0c;总结记录一次使用matplotlib绘制时序甘特图的经历。之所以要绘制这个时序甘特图&#xff0c;是因为22年数模研赛C…...

数据库概述、部署MySQL服务、必备命令、密码管理、安装图形软件、SELECT语法 、筛选条件

Top NSD DBA DAY01 案例1&#xff1a;构建MySQL服务器案例2&#xff1a;密码管理案例3&#xff1a;安装图形软件案例4&#xff1a;筛选条件 1 案例1&#xff1a;构建MySQL服务器 1.1 问题 在IP地址192.168.88.50主机和192.168.88.51主机上部署mysql服务练习必备命令的使用 …...

概率论与数理统计:第四章:随机变量的数字特征

文章目录 Ch4. 随机变量的数字特征1. 数学期望E(X)(1)数学期望的概念1.离散型①一维离散型随机变量X的数学期望&#xff1a; E X EX EX②一维离散型随机变量的函数的期望&#xff1a; E [ g ( X ) ] E[g(X)] E[g(X)]③二维离散型随机变量的函数的期望&#xff1a; E [ g ( X , …...

解决饿了么ui的对话框缩放和移动

import Vue from "vue";// v-dialogDrag: 弹窗拖拽水平方向伸缩 /** 使用方法* 将以下代码复制到一个js文件中&#xff0c;然后在入口文件main.js中import引入即可&#xff1b;* 给elementUI的dialog上加上 v-dialogDrag 指令就可以实现弹窗的全屏和拉伸了。* 给…...

Linux 中复制文件并保持修改时间等属性

一、遇到的问题 Linux使用cp命令复制文件备份时&#xff0c;发现文件的修改时间变成当前时间了&#xff0c;想要保留备份文件原有的修改时间及其它文件属性。 二、实现 1、cp命令 在 Linux 中&#xff0c;你可以使用 cp 命令来复制文件&#xff0c;并通过 -p 或 --preserve…...

Hugging News #0814: Llama 2 学习资源大汇总

每一周&#xff0c;我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新&#xff0c;包括我们的产品和平台更新、社区活动、学习资源和内容更新、开源库和模型更新等&#xff0c;我们将其称之为「Hugging News」。本期 Hugging News 有哪些有趣的消息&#xff0…...

​可视化绘图技巧100篇进阶篇(五)-阶梯线图(Step Chart)

目录 前言 图表类型特征 适用场景 图例 绘图工具及代码实现 ECharts SMARTBI...

GPT带我学-设计模式-命令模式

1 你知道设计模式的命令模式吗 是的&#xff0c;我知道设计模式中的命令模式。命令模式是一种行为型设计模式&#xff0c;它将请求封装成一个对象&#xff0c;从而允许使用不同的请求、队列或日志来参数化其他对象。命令模式还支持撤销操作&#xff0c;并且可以提供事务的实现…...

互联网发展历程:跨越远方,路由器的启示

互联网的蓬勃发展&#xff0c;一直在追求更广阔的连接&#xff0c;更遥远的距离。然而&#xff0c;在早期的网络中&#xff0c;人们面临着连接距离有限的问题。一项重要的技术应运而生&#xff0c;那就是“路由器”。 连接受限的问题&#xff1a;距离有限 早期的网络受限于直接…...

postman入门基础 —— 接口测试流程

一、编写接口测试计划 接口测试计划和功能测试计划目标一致&#xff0c;都是为了确认需求、确定测试环境、确定测试方法&#xff0c;为设计测试用例做准备&#xff0c;初步制定接口测试进度方案。一般来说&#xff0c;接口测试计划包括概述、测试资源、测试功能、测试重点、测试…...

springcloud+nacos实现灰度发布

灰度发布 gateway网关实现灰度路由 灰度发布实体 package com.scm.boss.common.bean;import lombok.Data; import lombok.experimental.Accessors;import java.io.Serializable;/*** 灰度发布实体*/ Data Accessors(chain true) public class GrayBean implements Serializ…...

AI 编程时代来了:为什么每个开发者都要学会用 AI 写代码

2026 年&#xff0c;不会用 AI 写代码的开发者&#xff0c;就像 2010 年不会用 Google 的程序员一样——不是不能工作&#xff0c;而是效率会被远远甩在后面。先看一组数字 根据 GitHub 2026 年开发者调查报告&#xff1a; 73% 的开发者在工作中使用了 AI 编程工具55% 的代码由…...

终极Mailtrain故障排除指南:10个常见问题与快速解决方案

终极Mailtrain故障排除指南&#xff1a;10个常见问题与快速解决方案 【免费下载链接】mailtrain Self hosted newsletter app 项目地址: https://gitcode.com/gh_mirrors/ma/mailtrain Mailtrain作为一款自托管的 newsletter 应用&#xff0c;为用户提供了强大的邮件营销…...

2026最新大模型应用开发学习路线(附时间规划,小白/程序员必收藏)

一、先破局&#xff1a;初学者必看&#xff01;Python 还是 Java 选对不踩坑 很多小白和入门程序员&#xff0c;刚接触大模型开发就卡在编程语言选择上&#xff0c;浪费大量时间纠结。不绕弯子&#xff0c;直接给结论&#xff0c;结合AI开发场景帮你精准选择&#xff0c;新手直…...

线程与进程的区别与联系:操作系统入门详解(含 Python 示例)

、先搞懂&#xff1a;进程与线程到底是什么&#xff1f;&#xff08;通俗类比官方定义&#xff09; 1.1 生活化类比&#xff1a;快速建立认知 如果把计算机的操作系统比作一个大型工厂&#xff1a; 进程&#xff1a;就是工厂里的一个个独立车间。每个车间有自己专属的生产资…...

从零开始:在VMware虚拟机中部署Qwen3.5-4B-Claude-4.6-Opus-Reasoning-Distilled-GGUF进行开发测试

从零开始&#xff1a;在VMware虚拟机中部署Qwen3.5-4B-Claude-4.6-Opus-Reasoning-Distilled-GGUF进行开发测试 1. 准备工作与环境搭建 在开始之前&#xff0c;我们需要准备好必要的软件和资源。首先确保你的主机系统满足以下要求&#xff1a; 至少16GB内存&#xff08;推荐…...

终极游戏画质升级指南:用OptiScaler解锁全显卡超采样自由

终极游戏画质升级指南&#xff1a;用OptiScaler解锁全显卡超采样自由 【免费下载链接】OptiScaler DLSS replacement for AMD/Intel/Nvidia cards with multiple upscalers (XeSS/FSR2/DLSS) 项目地址: https://gitcode.com/GitHub_Trending/op/OptiScaler OptiScaler是…...

BilibiliDown完整指南:三步掌握B站视频批量下载技巧

BilibiliDown完整指南&#xff1a;三步掌握B站视频批量下载技巧 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader &#x1f633; 项目地址: https://gitcode.com/gh_mirrors/bi/…...

连续使用 OpenClaw 50 天后,我总结了 3 个核心工作流和 5 个血泪教训

&#x1f525; 连续使用 OpenClaw 50 天后&#xff0c;我总结了 3 个核心工作流和 5 个血泪教训AI 不会取代你&#xff0c;但会用 AI 的人会取代你——这句话说烂了&#xff0c;但 50 天后我才真正明白它的意思。01 上周五下午 5 点&#xff0c;同事都在加班&#xff0c;我先走…...

告别彻夜等待:SteamShutdown让游戏下载完成后自动关机的智能解决方案

告别彻夜等待&#xff1a;SteamShutdown让游戏下载完成后自动关机的智能解决方案 【免费下载链接】SteamShutdown Automatic shutdown after Steam download(s) has finished. 项目地址: https://gitcode.com/gh_mirrors/st/SteamShutdown 你是否也曾经历过这样的困扰&a…...

告别单行代码:在Python IDLE中编写完整函数的完整指南

告别单行代码&#xff1a;在Python IDLE中编写完整函数的完整指南 对于刚接触Python的开发者来说&#xff0c;IDLE是一个既熟悉又陌生的环境。熟悉是因为它随Python安装包一起提供&#xff0c;陌生则是因为很多人仅仅把它当作一个简单的交互式Shell&#xff0c;而忽略了它作为完…...