我们在编写完代码并运行起来时,在我们的磁盘中会形成一个可执行文件,当我们双击这个可执行文件时(程序时),这个程序会加载到内存中,而这个时候我们不能把它叫做程序了,应该叫做进程。
所以说,只要把程序(运行起来)加载到内存中,就称之为进程。
从上述中我们会发现进程和程序并不是一个概念,简而言之:
程序:静态的,磁盘中生成的pro文件,叫程序
进程:程序的一次运行活动(程序跑起来,系统中就会多一个进程)
PCB:进程控制块(结构体)
当一个程序加载到内存中,操作系统要为刚刚加载到内存的程序创建一个结构体(PCB),进程信息被放在这个结构体中(PCB),可以理解为PCB是进程的属性的集合。
linux操作系统下的PCB:task_struct
task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息
在进程执行时,任意时间内,进程对应的PCB都要以下内容:
标示符、状态、优先级 、程序计数器 、内存指针、上下文数据、I/O状态信息 、记账信息 、其他信息
PCB通过双向链表相互连接,操作系统通过PCB,来找到进程。
使用ps指令查看,在实际工作中,配合grep来查找程序中是否存在某一个进程。
ps命令:
通过ps aux | grep 文件名来找
其中getpid()是找进程的标示符,getppid()找父进程的标示符
ps命令的参数以及作用:
参数 | 作用 |
---|---|
-a | 显示所有进程(包括其他用户的进程) |
-u | 用户以及其他详细信息 |
-x | 显示没有控制终端的进程 |
为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。
下面是kernel源代码里面的定义
/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"T (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
通过命令:ps aux,得到下面的如图红色框起来的表示该文件为可执行状态
值得注意的是:进程中的R状态不代表正在运行,代表的可被调度,此运行相当于上面的就绪态。
操作系统会把进程中R状态的进程全放在调度队列中,方便调度。
S状态是浅度睡眠,随时可以被唤醒,也可以被杀掉。
用代码创建一个睡眠状态的进程:
1)创建了一个可执行态进程
#include
#include
int main()
{
while(1);
return 0;
}
2)创建休眠态进程
#include
#include
int main()
{
while(1)
sleep(10);
return 0;
}
可以表示为深度睡眠,该进程不会被杀掉,即使你是操作系统,除非我自动唤醒,才可以恢复。
向进程发送SIGSTOP信号,该进程会响应该信号进入暂停状态, 向该进程发送SIGCONT信号,该进程会从暂停状态恢复到可执行状态。
死亡状态:进程被操作系统释放了或者自己退出了。
僵尸状态:一个处于僵尸状态的进程,会等待它的父进程或操作系统对它的信息进行读取,之后才会被释放。
cpu中的资源是有限的,不可能多个进程一起在CPU上运行,利用优先级把进程有效的先后排好,改善了系统的性能。
cpu资源分配的先后顺序,就是指进程的优先权(priority)
优先权高的有优先执行权。
用ps -l可以查看到进程的优先级
PRI:表示这个进程被执行的优先级,其值越小越早执行
NI:表示这个进程的nice值
nice值表示进程可被执行的优先级的修正值。
PIR=PIR(old)+nice。
当nice为负值时,那么该进程的优先级值会变小,优先级会变高,进程越快被执行。当然,nice也是有范围的,-20~19,一共40个级别。
环境变量(environment variables):一般是指在操作系统中用来指定操作系统运行环境的一些参数
先以windows为例来理解
我们咋windows双击软件就可以运行,不像linux需要打a.out,其实是我们再安装软件时,系统把软件的路径添加到了环境变量PATH中。
找到windows的环境变量:
打开控制面板——>点击“系统与安全”——>点击“查看计算机名称”——>找到高级系统设置,点击进去——>找到环境变量并点击进去
会得到下面这样一个页面
我们咋windows双击软件就可以运行,其实是我们再安装软件时,系统把软件的路径添加到了环境变量PATH中。
所以说,安装软件相当于拷贝到PATH中。
我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但
是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性
回到linux系统,如果我们想要查看环境变量,怎么办呢?
可以利用echo $name(name是指你要看的环境变量的名字)
常见的环境变量有PATH、HOME、SHELL
拿PATH来举例
在Linux中的一些指令是通过PATH环境变量来查找到指令的路径进而执行的。
拿ls
指令和自己写的代码程序来比较
创建text.c文件
#include
int main()
{
printf("hello PATH\n");
return 0;
}
这是因为在使用ls命令时,系统会通过PATH环境变量来查找ls,而a.out没办法通过PATH环境变量来找到,PATH环境变量中没有a.out的路径。
如何可以把自己写的文件可以像ls一样用呢?
把自己文件所在的路径添加到环境变量PATH中
通过export PATH=$PATH:a.out的所在的路径来
剩下的HOME、SHELL环境变量,如果感兴趣的话,可以看下面这个博客,这里就不展开来说了
大佬博客:【Linux入门】进程概念(超详解,建议收藏)_linux进程-CSDN博客
C程序的存储空间是如何分配的?
大佬博客:堆和栈详解
程序运行时的内存分区主要分为BSS段、数据段、代码段、堆、栈