【Linux】进程优先级 | 进程的切换 | 环境变量详解

news2025/3/14 10:33:21

  🤣 爆笑教程 👉 《看表情包学Linux》👈 猛戳订阅  🔥

💭 写在前面:我们先讲解进程的优先级,探讨为什么会存在优先级,以及如何查看系统进程、进程优先级的修改。然后讲解进程的切换,首次介绍进程的竞争性、独立性,以及并行和并发的概念,在通过讲解进程抢占引出可见寄存器与不可见寄存器。最后我们讲解环境变量,介绍环境变量 PATH,并且做一个 "让自己的可执行程序不带路径也能执行"的实践,讲解环境变量的到如何删除,最后再讲几个常见的环境变量。


Ⅰ. 进程优先级(Process Priority)

0x00 引入:什么是优先级?

我们先思考思考 权限 是什么?权限的本质是谈论 "能" 还是 "不能" 的问题。

那什么是 优先级 ?优先级是进程获取资源的先后顺序!

CPU 资源分配的先后顺序,就是指进程的优先权(priority)

优先权高的进程有优先执行权利。配置进程优先权对多任务环境的 Linux 很有用,可以改善系统性能,还可以把进程运行到指定的 CPU 上,这样一来就可以把不重要的进程安排到某个 CPU,可以大大改善系统整体性能。

0x02 为什么会存在优先级?

我们不妨先思考下我们日常生活中排队的本质,排队的本质可以说是 "确定优先级" ,

而插队行为就是更改优先级。因为排队造就了优先级,那我们为什么要排队?

​  可以不排队吗?可以,结果就是大家一窝蜂抢呗,全部用抢的。

"无理由暴力抢占式,优胜劣汰,我挤死你"

(前后时间来确认先后顺序) \rightarrow​ (谁能挤谁能撞谁就排到前面)

现实生活中一旦出现了抢,就难免会引发争执。

在比如说食堂买饭如果大家都不排队,如果你就是挤不过别人,就会一直买不到,

你就每次都要饿肚子,这在操作系统中叫做 "饥饿问题" 。

所以,排队主要是换了一种竞争方式,不以那么残酷的方式竞争,让进程都能 井然有序

我们之所以要排队,其实最主要的原因是因为资源不够!

如果资源是无限的,就像希尔伯特旅馆一样,该旅馆拥有无限多的房间,那也不需要排队的了。

200 名学生要去食堂吃饭,但窗口就 20 个,当然需要排队。如果窗口有 200 个,理论上不用排。

因为 系统里面永远都是进程占大多数,资源是少数。 这就导致了进程竞争资源是常态!

排队和进程资源竞争都是一定要确认先后的,它们的本质都是 确认优先级

本章我们要讲的是 Linux 的进程优先级,Linux 下的优先级有很多方式,包括设置和修改。

我们不建议修改优先级,如果你不懂调度器的调度算法,你随便修改优先级其实就是变相地 "插队" 了。你可以让你的进程尽快地得到了某种 CPU 资源或其它资源,凡是可能会打破调度器的平衡。其实你在用户层再怎么设置,也不会对调度器的调度策略产生什么影响。

再加上设置优先级没有什么意义,所以本章我们就不去讲解了。

0x03 查看系统进程:ps -l

🔍 查看系统进程:在 Linux 或者 Unix 系统中,输入  ps -l  命令则会输出内容:

$ ps -l    # 查看进程的优先级

我们写一个简单的 Hello 程序,令其每隔一秒发送一次 Hello

#include <stdio.h>
#include <unistd.h>

int main(void) {
    while (1) {
        sleep(1);
        printf("Hello!\n");
    }
}

我们把它运行起来,此时我们使用  ps -l   查看:

因为  ps -l  只能显示当前终端下进程的相关信息,我们可以使用给它加上 \textrm{-a}​ 选项:

$ ps -la   

 

此时我们的进程 process 就显示出来了,我们重点关注 \textrm{PRI}​ 和 \textrm{NI}​ 列。

 Linux 中的进程优先级由两部分组成:\textrm{PRI\, +\, NI}

  • \textrm{PRI}​:优先级 (priority),默认进程优先级为 80​。
  • \textrm{NI}​:nice 值 (nice value) ,进程优先级的修正属性,取值区间为 [-20, 19]​ ,默认值为 0​ 。

📌 注意:数字越小,表示优先级越高;数字越大,优先级越低。(Linux 下)

优先级的部分我们在 task_struct 中也是可以找到的。
它的优先级和我们上一章讲的进程状态一样,也是个整数,在 task_struct 中表示:

0x04 进程优先级的修改

要更该进程的优先级,需要更改的是 \textrm{NI}​,而非 \textrm{PRI}​ 。

因为 nice 值是进程优先级的修正数据,所以一个进程不管是在启动前还是在运行中,想要修改优先级,都是通过修改它的 nice 值来达到目的。

其实,我们系统中是存在   nice  命令的,对应的还有   renice  。

$ nice  
$ renice

它们可以让我们在启动一个进程时直接指定优先级,或者启动中或启动前设置优先级。

感兴趣可以自行查阅,我们还是主要学习如何使用   top  命令去修改:

$ top

进入 top 后我们键入 \textrm{r}​ ,此时会发出询问:PID to renice [default pid=x]

在后面输入我们要修改的进程的 \textrm{pid}​ 即可,我们刚才进程的 \textrm{pid}​ 是 20332​:

然后会询问:PID to renice [default pid=1] 问你要设置哪个进程的 \textrm{pid}​:

这里居然提示  Failed  修改失败了!Permission denied (么得权限) !

​ 因为我们刚才说过:

"一个进程的优先级不能轻易被修改,因为会打破调度器的平衡"

如果你执意修改,你须具备 👑 超级用户 的权限 —— \textrm{root}​ !这里我们 sudo top 就行:

$ sudo top

 

 ​ 找到了找到了,我们继续,我们继续!

我们刚才将 nice 值修改为 -20,现在 \textrm{PRI}​ 优先级变成 60 了。

值得强调的是,Linux 不允许用户无节制地设置优先级,设置的优先级范围不能逾过下列区间:

\textrm{NICE}:\, [-20,19]

其取值范围是 -20​ 至 19​,一共 40 个可设置级别。

\textrm{PRI}​ 值越小越快被执行,Linux 的优先级是这样设置的:

prio = prio_old + nice;

所以,只需要改 nice 优先级就能变化。

📌 注意:每次设置优先级,这个 old 优先级都会被恢复成为 80 (跟上一次没关系)

Ⅱ. 进程的切换(Process Switch)

0x00 竞争与独立

竞争性:僧多粥少!系统进程数目众多,而 CPU 资源只有少量,甚至一个,所以进程之间是具有竞争属性的。为了高效的完成任务、更合理竞争相关资源,便具有了优先级。

独立性:多进程运行,需要独享各种资源,多进程运行期间互不干扰。

进程运行具有独立性,不会因为一个进程挂掉或者异常而导致其它进程出现问题!

内核结构 + 代码和数据

❓ 思考:那么操作系统是如何做到进程具有独立性的呢?

(我们将在后续讲解进程地址空间时揭晓)

0x01 并行和并发

并行:多个进程在多个 CPU 下分割,同时进行运行,我们称之为并行。
并发:多个进程在单个 CPU 下采用进程切换的方式,在一段时间内,让多个进程都得以推进,称之为并发。

下面我们来理解一下并行与并发。

一般服务器都是双 CPU 的,所以双 CPU 的系统是存在的,就会存在多个进程同时在跑的情况。

如果存在多个 CPU 的情况,任何一个时刻,都有可能有两个进程在同时被运行 —— 并行 

但我们大家接触的、用的笔记本电脑基本都是单核的,单 CPU 的任何时刻只允许一个进程运行。

我的电脑是单 CPU 的,但是我的电脑中有各种进程都可以在跑啊?怎么肥事啊?

它是怎么做到的呢?

不要认为进程一旦占有 CPU,就会一直执行到结束,才会释放 CPU 资源。

所以一直让它跑,直到进程执行完,是不存在的,我们遇到的大部分操作系统都是 分时 的!

操作系统会给每一个进程,在一次调度周期中,赋予一个 时间片 的概念。

例:一秒钟之内每一个进程至少要被调度20次,每一次调度就是自己代码得以推进的时候。

在一个时间段内,多个进程都会通过 "切换交叉" 的方式,当多个进程的代码,在一段时间内都得到推进 ——  并发

0x02 进程抢占

❓ 思考:OS 就是简单的根据队列来进行前后调度的吗?有没有可能突然来了一个优先级更高的进程?

抢占式内核!我们现在的计算机基本都是支持 抢占 的。正在运行的低优先级进程,可能正在享受着它的时间片、推进着代码,但是如果来了优先级更高的进程,我们的调度器会直接把对应的进程从 CPU 上剥离,放上优先级更高的进程,这个操作就叫做 进程抢占

了解

a. 不允许不同优先级的进程存在的 
b. 相同优先级的进程,是可能存在多个的

task_struct* queue[5];

根据不同的优先级,将特定的进程放入不同的队列中!这其实就是一张简单的哈希表,后面列入的都是队列,其原理是通过哈希根据不同的哈希值确定队列的优先级,每一种优先级 Linux 都会维护一个队列。

举个最简单的例子,下面的 z 是如何得到已经释放的临时变量 a 的数据的?

int func() {
    int a = 10 + 20;
    return a;
}

int z = func();

寄存器功不可没,拷贝一份到寄存器里去,然后再 \textrm{mov} 给 z 变量。

CPU 内的寄存器是:可以临时地存储数据

寄存器分为 可见寄存器 不可见寄存器

当进程在被执行的过程中,一定会存在大量的临时数据,会暂存在 CPU 内的寄存器中。

寄存器上数据的重要性:

我们把进程在运行中产生的各种寄存器数据,我们叫进程的硬件上下文数据。

  • 当进程被剥离:需要保存上下文数据
  • 当进程恢复时:需要将曾经保存的上下文数据恢复到寄存器中。

上下文在哪里保存?task_struct !

📌 注意事项:要准确区分,"寄存器" 和 "寄存器里的数据" 的区别。

  • 寄存器只有一套,但是寄存器里的数据有多份。

Ⅲ. 环境变量(Environment Var)

0x00 引入:思考一个问题

❓ 思考:为什么我们的代码运行要带路径,而系统的指令不用带路径?

如果我们直接输入我们的可执行程序,会显示 bash: process: command not found 

我们说过,执行系统的指令实际上也是程序,系统的指令你也是可以带上路径的:

其实,我们可以通过它的报错 "command not found" 发现些什么!

要执行一个可执行程序,前提是要先找到它。

现在我们的问题就可以转化成:为什么系统的命令能找到,而我们自己的程序找不到?

💡 真相

系统中是存在相关的 环境变量,保存了程序的搜索路径的!

为什么我们的代码运行要带路径,而系统的指令不用带?其本质是由环境变量 \textrm{PATH} 引起的!

0x01 环境变量 PATH 

我们可以通过 env 指令查看环境变量:

$ env

这些变量每一个都有它特殊的用途,系统中搜索可执行程序的环境变量叫做 \textrm{PATH}

我们可以通过 grep 去抓一下:

如何查看环境变量的内容?我们可以使用 echo  去显示:

$ echo $PATH

 在 \textrm{PATH} 前加上 $ 符即可打印出环境变量:

环境变量 \textrm{PATH} 中会承载多种路径,中间用冒号 ( : ) 作为分隔符。

我们再执行某一个程序时,比如执行 ls 时,我们的系统识别到 ls 的输入时,会在上面路径中逐个搜索,只要在特定的路径下找到了 ls,就会执行特定路径下的 ls 并停止搜索。

换言之,\textrm{PATH} 就提供了环境变量,可执行程序搜索的路径。

我们的 ls 在  usr/bin  路径下,这说明当前的 ls 在 \textrm{PATH} 中是可以被找到的,

所以执行 ls 的时侯自然可以不带路径,所以我们自己的  process 不带路径自然就不能执行。

因为当前的  process 所在的路径并没有这里的环境变量,程序在搜索的时侯找了路径也没有找到你这个可执行程序,搜索完找不到,自然就报 "command not found" 了。

0x02 实践:让自己的可执行程序不带路径也能执行

那我现在就想让我的可执行程序 process 不带路径直接执行起来,可以吗?

可以!我们先讲述一种简单粗暴的方式,直接把我们的可执行程序 cp 拷贝到系统的路径中:

$ sudo cp process /usr/bin/

既然系统的所有命令都在 usr/bin 路径下,那我们把我们的 process 拷进去就行了。

实际上,刚才那个操作我们可以称之为 "软件被安装到系统上",但是我们不建议你去自己安装。

也更不建议你将你的指令拷贝到 Linux 系统路径下,因为这会污染 Linux 下的命令池。

经常这么干时间久了你可能都忘了这个是干什么的,半年之后:

"诶!我这系统里怎么还有个 process?"

可能就分不清是你写的还是系统的了,所以我们不建议这么做!

更好的方式是将 process 所处的路径也添加到环境变量中。

前置:在 Linux 命令行中,我们也是可以定义变量的,命令行变量分为两种:

  • 普通变量
  • 环境变量(具备全局属性)

命令行上直接写,变量名等于值,你所定义的这个变量 a,就是 本地变量

(我们这里先对本地变量做一个小小的理解,稍后我们还会讲解的)

用系统查看环境变量的命令 env 去查看一下这个本地变量,会发现根本找不到,

因为它不以环境变量的形式存在,但是它是存在的!

如果你想让一个变量变成环境变量,你可以通过 export 导出一个在系统中可以查看的环境变量:

$ export []=[]

通过 env 并 grep 一下这个变量,我们就能找到我们导出的环境变量了:

(至于环境变量和本地变量之间的差别,我们稍后再讲)

现在我们知道该如何导环境变量了,现在我想执行我的程序不想再带路径该怎么办呢?

💭 操作演示:下面我们来做个好玩的:

把我们的环境变量,当前路径导入到 \textrm{PATH} 路径中看看会发生什么:

$ export PATH=[路径]

这么一导之后,我们发现我们的 process 可以跟系统指令一样不带路径直接执行了:

但是好像我们的系统指令全都寄了!!!

 啊这,怎么会这样呢?!

因为你把 \textrm{PATH} 里的环境变量都搞没了,只剩你自己的路径了,所以这些指令自然都找不到了。

出现了你刚才自己可执行程序不带路径后 Enter 的报错 "command not found" 。

 这……难道环境污染了(紧张)?我的要服务器坏掉了(害怕)?

不用担心!在命令行上设置的环境变量是具有临时性的,只在你登陆期间有效。

你刚才的修改只是在内存中的修改,不会修改系统当中的相关配置文件。

所以你只需要关掉重开就行了,随便搞,不会影响。

如果你想让你的环境变量设置永久有效的话,是需要更改配置文件的,该配置文件在系统当中,跟云服务器没有关系。

那我们该怎么做呢?来,这么做:

$ export PATH=$PATH:[路径]

0x03 环境变量的导入和解除

刚才我们通过 export 去导入变量,如果想取消一个变量,就可以使用 unset 来取消变量设置:

此时我们使用 unset 环境变量,就可以解除 foo:

" 这些东西实际上都是 shell 命令,export 是导出,unset 是取消 "

0x04 介绍几个常见的环境变量

刚才我们介绍了环境变量 \textrm{PATH},它是用来指定命令的搜索路径的。 

下面我们来详细介绍一下常见的环境变量,刚才我们就是用 env 指令去查看环境变量的:

我们能看到有很多环境变量,比如下面这个 \textrm{HOSTNAME} 就是表示 "对应这台主机的主机名" 。

我们同样也是可以通过 echo 指令带上 $ 去查看环境变量:

echo $HOSTNAME

再比如 \textrm{SHELL},它可以告诉你你的 shell 在哪里,通常是 /bin/bash 

echo $SHELL

得益于 Linux 存在历史命令的记录功能,我们可以在 Xshell 里 ↑ ↓ 显出历史命令,就像这样: 

"总不能一直记吧?肯定是有个指令记录的阈值的!"

没错!Linux 最多允许你记录的历史命令条数是 3000。

而我们接下来要介绍的 \textrm{HISTSIZE}  (History Size),就是定义一共记录多少历史指令的环境变量:

$ echo $HISTSIZE

顺便一提,我们可以通过 history 命令令去查看我们历史敲过的所有命令:

 再来!我们再说几个 ~

我们一般是通过 whoami 指令去查看当前是谁正在使用系统的,而 \textrm{USER} 就记录了当前谁在用。

$ echo $USER

 ​​​​​​

不知道大家有没有关注过,每次登陆服务器默认所处的路径?就是默认所处的工作目录。

root 用户的工作目录和普通用户的工作目录不同,那 Linux 是如何知道的呢? 

\textrm{HOME}:指定用户的主工作目录(即用户登陆到 Linux 系统中时,默认的目录)

当然还有很多,比如 \textrm{SSH-CLIENT} 记录了谁登的服务器、地址、端口号等。

(环境变量实在多,全部讲完不太现实,上面我们讲的都是一些常用的,欢迎补充)

0x05 尾记

命令行中启动的进程,父进程全部都是 bash 。

环境变量具有全局属性,环境变量是会被子进程继承下去的。

所谓的本地变量,本质就是在 bash 内部定义的变量,不会被子进程继承下去。

Linux 下大部分命令都是通过子进程的方式执行的,但是还有一部分命令不通过子进程的方式执行,而是由 bash 自己执行(调用自己的对应的函数来完成特定的功能,比如 cd 命令),我们把这种命令叫做 内建命令

📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2022.3.
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,
              本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.

比特科技. Linux[EB/OL]. 2021[2021.8.31 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/335091.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SpringBoot的器材管理系统

介绍有一家实验室&#xff0c;里面有100台实验设备&#xff0c;5个实验员。每个设备使用之前需要对设备进行检查&#xff0c;现在存在以下痛点&#xff1a; 实验员检查器材的时候&#xff0c;发现器材不见了&#xff0c;他们都不知道器材是坏了还是其他实验员用到其他器材。非常…

传奇GOM引擎配置PAK密码补丁教程

因为我很少接触GOM引擎&#xff0c;所有很晚才知道PAK密码的事情&#xff0c;以前经常在群里或者QQ上有人问站长&#xff0c;说补丁有PAK密码怎么办&#xff0c;我起初不在意&#xff0c;限制发现是一个大问题&#xff0c;好吧&#xff0c;今天借助这篇文章&#xff0c;分享一下…

Python获取公众号(pc客户端)数据,使用Fiddler抓包工具

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 今天来教大家如何使用Fiddler抓包工具&#xff0c;获取公众号&#xff08;PC客户端&#xff09;的数据。 Fiddler是一个http协议调试代理工具&#xff0c;它能够记录并检查所有你的电脑和互联网之间的http通讯&#xff0c;…

Spring JdbcTemplate 和 事务

JdbcTemplate概述 JdbcTemplate是spring框架中提供的一个对象&#xff0c;是对原始繁琐的Jdbc API对象的简单封装。spring框架为我们提供了很多的操作模板类。例如&#xff1a;操作关系型数据的JdbcTemplate和&#xff0c;操作nosql数据库的RedisTemplate&#xff0c;操作消息…

UDP协议

文章目录一、前沿知识应用层传输层二、UDP协议一、前沿知识 应用层 应用层&#xff1a;描述了应用程序如何理解和使用网络中的通信数据。 我们程序员在应用层的主要工作是自定义协议&#xff0c;因为下面四层都在系统内核/驱动程序/硬件中已经实现好了&#xff0c;不能去修改…

【数据集】中国各类水文专业常用数据集合集

1 水文气象数据 1.1 中国站点尺度天然径流量估算数据集&#xff08;1961&#xff5e;2018年&#xff09; 论文&#xff1a; J2022-High-quality reconstruction of China’s natural streamflow-缪驰远&#xff08;北京师范大学地理科学学部&#xff09; 研究内容&#xff1a…

TLV73312PQDRVRQ1稳压器TPS622314TDRYRQ1应用原理图

一、TLV73312PQDRVRQ1低压差稳压器 1.2V 300MATLV733 300mA 低压差稳压器是有 300mA 拉电流能力的超小型、低静态电流 LDO&#xff0c;具有良好的线路和负载瞬态性能。这些器件具有 1% 的典型精度。TLV733 系列设计具有先进的无电容器结构&#xff0c;确保无需输入或输出电容器…

thinkPHP6接入workman

上篇介绍了workman实现websocket功能&#xff08;链接&#xff1a;https://blog.csdn.net/weixin_38155824/article/details/128952037&#xff09; 这篇就介绍如何在thinkPHP6项目中接入workman。 利用TP6的自定义命令开启websocket服务 查看TP6手册&#xff1a;命令行>自…

Oracle Dataguard(主库为 Oracle rac 集群)配置教程(01)—— dataguard 服务器安装 Oracle 软件

Oracle Dataguard&#xff08;主库为 Oracle rac 集群&#xff09;配置教程&#xff08;01&#xff09;—— dataguard 服务器安装 Oracle 软件 / 本专栏详细讲解 Oracle Dataguard&#xff08;Oracle 版本为11g&#xff0c;主库为双节点 Oracle rac 集群&#xff09;的配置过程…

共享模型之无锁(二)

1.原子基本类型 1>.J.U.C并发包提供了多个原子基本类型: AtomicBoolean AtomicInteger AtomicLong ...2>.以AtomicInteger为例: public class TestAtomicIntegerDemo01 {public static void main(String[] args) {//原子整型类AtomicInteger i new AtomicInteger(0);…

linux入门---基础指令(上)

这里写目录标题前言ls指令pwd指令cd指令touch指令mkdirrmdirrmman指令cp指令mv指令前言 我们平时使用电脑主要是通过鼠标键盘以及操作系统中自带的图形来对电脑执行相应的命令&#xff0c;比如说我想打开D盘中的cctalk这个文件&#xff1a; 我就可以先用鼠标左键单击这个文件…

负载均衡的方式

在业务初期&#xff0c;我们一般会先使用单台服务器对外提供服务。随着业务流量越来越大&#xff0c;单台服务器无论如何优化&#xff0c;无论采用多好的硬件&#xff0c;总会有性能天花板&#xff0c;当单服务器的性能无法满足业务需求时&#xff0c;就需要把多台服务器组成集…

五岳科技与亚马逊云科技,助力中国产品实现全球品牌力提升

随着DTC模式实践在全球跨境电商市场取得成功&#xff0c;越来越多中国品牌走出国门&#xff0c;走向世界。而文化差异、语言隔阂、信息差等始终是行业中的共同难题&#xff0c;如何提高竞争壁垒与解决数据困境成为企业的共同需求。 作为一家致力于用AI技术赋能传统行业升级以…

将群晖NAS变为本地盘

本文介绍一个工具&#xff0c;可以在 Windows 系统下将群晖NAS的目录变为本地盘&#xff0c;好处是在外部访问的时候&#xff0c;能够大大改善体验。可以用本地的应用程序直接打开&#xff0c;速度依赖网络带宽&#xff0c;正常情况下&#xff0c;看视频是没有问题的。当然&…

MySQL入门篇-Xtrabackup详细介绍

Xtrabackup简介 MySQL冷备、mysqldump、MySQL热拷贝都无法实现对数据库进行增量备份。在实际生产环境中增量备份是非常实用的&#xff0c;如果数据大于50G或100G&#xff0c;存储空间足够的情况下&#xff0c;可以每天进行完整备份&#xff0c;如果每天产生的数据量较大&#…

Vue3 企业级优雅实战 - 组件库框架 - 11 组件库的打包构建和发布

回顾第一篇文章中谈到的组件库的几个方面&#xff0c;只剩下最后的、也是最重要的组件库的打包构建、本地发布、远程发布了。 1 组件库构建 组件库的入口是 packages/yyg-demo-ui&#xff0c;构建组件库有两个步骤&#xff1a; 添加 TypeScript 的配置文件&#xff1a; tsco…

百趣代谢组学资讯:槟榔的基因组为雌雄同株植物的性别决定提供见解

文章标题&#xff1a;The genome of Areca catechu provides insights into sex determination of monoecious plants 发表期刊&#xff1a;New Phytologist 影响因子&#xff1a;10.323 作者单位&#xff1a;海南大学 百趣生物提供服务&#xff1a;植物激素高通量靶标定…

怎么查看自己的电脑IP地址?

作为一个互联网冲浪侠&#xff0c;你应该对IP地址并不陌生&#xff1a;访问网站和网络服务器知道你的IP地址&#xff1b;发送的电子邮件头包含你的IP地址。如果有人想从IP地址追踪到你的物理地址和身份&#xff0c;是有可能的。 IP地址代表互联网协议地址。它是一个特殊的号码…

linux高级命令系列一

重定向命令学习目标能够使用重定向命令将终端显示内容重定向到文件1. 重定向命令的介绍重定向也称为输出重定向&#xff0c;把在终端执行命令的结果保存到目标文件。2. 重定向命令的使用命令说明>如果文件存在会覆盖原有文件内容&#xff0c;相当于文件操作中的‘w’模式>…

C/C++:预处理(下)

目录 一.回顾程序的编译链接过程 二. 预处理之预定义#define 1.#define定义的标识符 2.#define定义的宏 3.带副作用的表达式作为宏实参 4.两个经典的宏 5.#define使用的一些注意事项小结 6.宏与函数的比较 7.#undef 附&#xff1a;关于#define的三个冷知识 三. 条件…