概述
以下是阿鲤对Linux系统中进程的总结,希望对大家有所帮助,若有不足之处请慷慨提出。
一:操作系统的介绍
1.1:操作系统的定位:
1.2:操作系统的管理方式:
二:进程概念
2.1:进程是什么?
2.2:Linux下进程的查看
2.3:进程状态
2.4:进程创建
2.5:僵尸进程
2.6:孤儿进程
2.7:进程优先级
注:以下介绍均是基于centos7所实现的
一:操作系统的介绍
1.1:操作系统的定位:
操作系统是一个管理的软件--管理着计算机上的软硬件资源
1.2:操作系统的管理方式:
操作系统对计算机中的软硬件管理是通过先描述再组织的;
硬件:操作系统通过驱动程序收集硬件信息,然后再进行管理;
软件:因为操作系统是不会让用户直接访问内核并且内核的调用方式异常复杂,所以通过软件对这些调用进行封装,通过封装的接口对计算机进行操作。
注:库函数是对系统调用接口的封装
二:进程概念
2.1:进程是什么?
再windows下有一个任务管理器,打开任务管理器我们就会发现打一个就是进程;
然后你就会发现进程里面的内容都是正在运行中的程序,所以对于进程的简单理解可以理解为正在运行的程序,但是对于我们而言这样浅显的认识是不足够的。
我们再使用计算机的时候可以变听音乐变使用qq聊天,但是我们的电脑只有一个cpu那么操作系统是如何通过一个cpu来运行多个文件的呢?
在这里操作系统采用的是分时机制,即把一大段时间分为许多小段,每一小段时间分配给每一个需要运行的程序,因为每个小段的时间片非常短所以在用户看来程序是一直在运行的。那么操作系统是如何做到快速的切换程序呢?
在这里就涉及到了操作系统先描述后组织的管理方式了,即每一个程序都会对应着自己的一个描述信息;而这里的描述信息就是我们所说的进程(PCB),而在Linux中PCB就是一个结构体指针struct sask_struct,而这个指针所指向的就是对应程序的地址,Linux中的PCB中还会记录以下信息:
内存指针 | 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针 |
上下文进程 | 进程执行时处理器的寄存器中的数据 |
程序计数器 | 程序中即将被执行的下一条指令的地址 |
标识符 | 描述本进程的唯一标示符,用来区别其他进程 |
状态 | 任务状态,退出代码,退出信号等 |
优先级 | 相对于其他进程的优先级 |
I/O状态信息 | 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表 |
记账信息 | 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等 |
其他信息 | 信息很多。。。。。。 |
注:linux中pcb之间的练习是通过双向链表实现的。
2.2:Linux下进程的查看
在linux下进程查看进程可以在/proc系统文件中查看(数字都时进程ID)
当然我们以可以使用ps命令来查看进程
1)ps a 显示现行终端机下的所有程序,包括其他用户的程序。
2)ps -A 显示所有程序。
3)ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。
4)ps -e 此参数的效果和指定"A"参数相同。
5)ps e 列出程序时,显示每个程序所使用的环境变量。
6)ps f 用ASCII字符显示树状结构,表达程序间的相互关系。
7)ps -H 显示树状结构,表示程序间的相互关系。
8)ps -N 显示所有的程序,除了执行ps指令终端机下的程序之外。
9)ps s 采用程序信号的格式显示程序状况。
10)ps S 列出程序时,包括已中断的子程序资料。
11)ps -t <终端机编号> 指定终端机编号,并列出属于该终端机的程序的状况。
12)ps u 以用户为主的格式来显示程序状况。
13)ps x 显示所有程序,不以终端机来区分。
14)ps -l 較長,較詳細的顯示該PID的信息
eg:常用
ps -ef (粗略)
ps -aux (详细)
UID | 属于的用户 |
%CPU | cpu使用率 |
PID | 进程的标识符 |
%MEM | 内存使用率 |
PPID | 父进程的PID |
RSS | 物理内存使用大小 |
VSZ | 虚拟内存使用大小 |
STAT | 进程状态 |
STIME | 起始的运行时间 |
TTY | 终端信息 |
TIME | 在cpu上运行的时长 |
CMD | 运行的具体程序名称 |
2.3:进程状态:
粗略的说进程状态可分为运行 就绪 阻塞这三种状态,而在真正细分时应该分为以下几种
运行状态R | 正在运行及拿到时间片就能运行的进程 |
可中断休眠状态S | 休眠的进程随时可被唤醒 |
不可中断休眠状态D | 休眠的进程不能被唤醒,只能等到资源条件满足自然唤醒 |
停止状态T | 一种空洞的状态 |
僵死状态Z | 已经停止的进程资源没有被释放 |
状态+ | 前台进程 |
eg:首先我们写一个这样的程序:
然后生成一个BelongAl的可执行文件,然后运行它,
然后使用ps -aux | grep -BelongAl查看进程
我们可以看到它的进程状态时S+即处于可终端休眠的前台进程,我们刚才写的程序明明是一个一直在运行的程序为什么现在进程的状态时S+呢?
这是因为在上面的程序中我们使用了printf()函数来进行写入,既然有写入那就有等待,而I/O的速度远慢于cpu的处理速度所以状态看起来就是S+了。
接下来我们将程序改成这样
然后重新生成一个BelongAl的可执行文件,然后运行它,
然后使用ps -aux | grep -BelongAl查看进程
我们就可以看到BelongAl的进程状态就变成了R+,这是因为改动后的程序一直都在执行着cpu计算。
然后我们使用Ctrl+Z 再查看BelongAl的进程信息
你会发xianzaiBelongAl的进程状态变成了T;但是我们前面也说了T状态的进程会占用资源,那么怎样删除它呢?
在linux中有一个kill命令是用来杀死进程的但是当你在使用kill对T状态的进程使用时你会发现是没有用,这是因为T状态的进程是无任何感知的,所以在这里我们只能使用kill -9来强行删除进程,如下
2.4:进程创建
在linux中有以下两个接口
fork():通过复制一个父进程创建一个子进程
eg:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
printf("********%dn",getpid());
pid_t pid = fork();
if(pid < 0)
{
printf("fork errprn");
return -1;
}
else if(pid == 0)
{
//这段代码只能子进程能访问到
printf("this is child--%dn",getpid());
}
else if(pid > 0)
{
//这段代码只有父进程能够运行到
printf("this is parent--%dn",getpid());
}
//下面的代码父子进程均可以运行到
while(1)
{
printf("parent and child%dn",getpid());
sleep(1);
}
printf("W-Rn");
return 0;
}
然后我们将程序运行起来查看就可以看到以下情况
然后查看进程就会发现出现了父子进程
注意:
1:子进程的创建时通过复制父进程的信息,所以子进程所运行的代码是从成功创建之后运行的;
2:父子进程之间具有代码共享数据独有的特点
3:使用fork()创建子进程fork时会有三种返回值,当返回值等于于0时代表只有子进程可以访问;当返回值大于0时代表只有父进程可以访问;当返回值小于0时代表创建出错;
2.5:僵尸进程
我们在进程状态中介绍时我们没有提到僵死状态的进程,这是因为僵死状态的进程危害很大,所以我们需要单拎出来介绍;我们称僵死状态的进程为僵尸进程;
僵尸进程产生的原因:子进程先于父进程退出,退出后,为了保存自身的退出原因(返回值),因此资源没有完全释放,操作系统这时候通知父进程获取子进程的退出状态,并允许操作系统释放资源,但是若父进程没有关注这个退出状态,则子进程虽然退出了,但是资源没有完全释放,处于僵死状态。
僵尸进程的危害:资源泄露
eg:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
printf("********%dn",getpid());
pid_t pid = fork();
if(pid < 0)
{
printf("fork errprn");
return -1;
}
else if(pid == 0)
{
printf("this is child--%dn",getpid());
exit(0);//退出子进程
}
else if(pid > 0)
{
printf("this is parent--%dn",getpid());
}
//下面的代码父子进程均可以运行到
while(1)
{
printf("parent and child%dn",getpid());
sleep(1);
}
return 0;
}
然后查看进程我们就会发现子进程变成了僵尸进程
2.6:孤儿进程
孤儿进程的产生原因:父进程先于子进程退出
eg:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
printf("********%dn",getpid());
pid_t pid = fork();
if(pid < 0)
{
printf("fork errprn");
return -1;
}
else if(pid == 0)
{
//这段代码只能子进程能访问到
printf("this is child--%dn",getpid());
}
else if(pid > 0)
{
//这段代码只有父进程能够运行到
printf("this is parent--%dn",getpid());
exit(pid);
}
//下面的代码父子进程均可以运行到
while(1)
{
printf("parent and child%dn",getpid());
sleep(1);
}
printf("W-Rn");
return 0;
}
然后运行该段代码你会发现你使用Ctrl+C不能使它停下来,就如同下面
然后我们查看进程
我们会发现子进程现在变成了S的状态,是一个后台进程;所以不能停下来;所以我们只能kill掉它。
注:父进程先于子进程退出,子进程成为孤儿进程,运行在系统后台,并且被1号进程收养;而且孤儿进程不会变成僵尸进程,一退出会直接被1号进程所接收。
2.7:进程优先级
决定进程cpu调度优先权的级别,从而让操作系统更好的运行
那么程序的优先级越高它的性能就越高吗?
当然不是了,在我们所写的程序中可大体分为两类,cpu密集型和io密集型,因为io密集型大部分时间都在等待输入所以增加io密集型程序对提高它的效率影响不大。
查看优先级
我们使用ps -efl|head -n 1可以看到以下信息
修改优先级
其中PRI就是优先级;那么PRI怎样修改呢?(PRI越小优先级越高)
首先PRI是不能直接修改的,它存在这样一个公式PRI = PRI + NI;所以我们能通过更改NI值来改变优先级
使用renice -n -100 -p PID:把PID的NI值修改为-100(但是NI值有最小下限(-20 - 100))
最后
以上就是愉快母鸡为你收集整理的详细介绍Linux系统中的进程的全部内容,希望文章能够帮你解决详细介绍Linux系统中的进程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复