• 进程
是指一个具有独立功能的程序在某个数据集上的一次动态运行过程,它是系统进行资源分配和调度的最小单元。
• 一个进程能够拥有多个线程。每一个线程必须有一个父进程。
• 进程特性:并发、动态、交互、独立和异步。
进程的生命周期
进程的五种状态
• 执行(TASK_RUNNING)
进程正在被CPU运行,或已经准备就绪随时可由调度程序运行
• 僵尸(TASK_ZOMBIE)
当进程已停止执行,但其父进程还没有调用wait()询问其状态时,则称该进程处于僵死状态。
• 停止(TASK_STOPPED)
当进程收到信号SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU时就会进入暂停状态。可向其发送SIGCONT信号让进程转换到可执行状态。
• 睡眠状态
假设进程在内核态运行时须要等待系统的某个资源,此时该进程就会调用sleep_on()或interruptible_sleep_on()自愿地放弃CPU的使用权。而让调度程序去运行其它进程。这时称其处于睡眠等待状态。
– 可中断(TASK_INTERRUPTIBLE)
进程在该状态下。系统不会调度该进程运行。
当系统产生一个中断。
或者释放了进程正在等待的资源,
或者进程收到一个信号。
都能够唤醒进程转换到就绪状态(就可以执行状态)。
– 不可中断(TASK_UNINTERRUPTIBLE)
除了不会由于收到信号而被唤醒。该状态与可中断睡眠状态类似。但处于该状态的进程仅仅有被使用wake_up()函数明白唤醒时才干转换到可执行的就绪状态。该状态通常在进程须要不受干扰地等待或者所等待事件会非常快发生时使用。
进程上下文
• 每一个进程都有各自互不干涉的进程地址空间。该地址空间是大小为 4GB的线性虚拟空间,用户所看到和接触到的都是该虚拟地址,无法看到实际的物理内存地址。利用这样的虚拟地址不但能起到保护操作系统的效果(用户不能直接訪问物理地址),并且,更重要的是。用户程序能够使用比实际物理内存更大的地址空间。
• 4GB的进程地址空间会被分成两个部分:用户空间与内核空间。
• 用户地址空间是从0到3GB(0xC0000000),
• 内核地址空间占领3GB到4GB。
• 用户进程通常情况下仅仅能訪问用户空间的虚拟地址,不能訪问内核空间的虚拟地址。
• 仅仅实用户进程使用系统调用(代表用户进程在内核态运行)时能够訪问到内核空间。
• 每当进程切换时,用户空间就跟着变化;
• 而内核空间由内核负责映射,它不会跟着进程改变。是固定的。
• 内核空间地址有自己相应的页表,用户进程各自有不同的页表。
• 每一个进程的用户空间都是全然独立、互不相干的。
• BSS段:在採用段式内存管理的架构中。BSS段(bss segment)一般是指用来存放程序中未初始化的全局变量的一块内存区域。
BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。
• 数据段:在採用段式内存管理的架构中,数据段(data segment)一般是指用来存放程序中已初始化的全局变量的一块内存区域。
数据段属于静态内存分配。
• BSS段:在採用段式内存管理的架构中,BSS段(bss segment)一般是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。
BSS段属于静态内存分配。
• 数据段:在採用段式内存管理的架构中。数据段(data segment)一般是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。
• 代码段:在採用段式内存管理的架构中,代码段(code segment / text segment)一般是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序执行前就已经确定,而且内存区域通常属于仅仅读, 某些架构也同意代码段为可写。即同意自改动程序。
在代码段中,也有可能包括一些仅仅读的常数变量,比如字符串常量等。
• 栈(stack)在计算机科学中,是一种特殊的链表形式的数据结构,它的特殊之处在于仅仅能同意在链表的一端(称为栈顶。英文为top)进行加入和删除操作。另外堆栈数据结构的实现也能够通过数组来完毕。栈Stack是存放程序中局部变量的内存区。另外栈stack用来保存函数调用的现场。栈stack由系统自己主动分配。用户不须要关心其分配和释放。
• 堆是指Heap,程序执行时供程序猿来支配的一段内存。 用于进程执行时动态分配内存。堆的大小不固定。可依据程序执行动态变化。
由程序中的new/delete等控制。
fork方法
• fork()函数用于从已存在的一个进程中创建一个新的进程,新进程称为子进程,而原进程称为父进程。
• 使用fork()函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间,包含进程上下文、代码段、进程堆栈、内存信息、打开的文件描写叙述符、信号控制设定、进程优先级、进程组号、当前工作文件夹、根文件夹、资源限制和控制终端等,而子进程所独有的仅仅有它的进程号、资源使用和计时器等。
• 区分父子进程:由于子进程差点儿是父进程的全然复制,所以父子进程会执行同一个程序。这就须要用一种方式来区分它们,并使它们照此执行。在父进程中的返回值是子进程的进程号,而在子进程中返回0。
因此,能够通过返回值来判定该进程是父进程还是子进程。
• 开销:使用fork()函数的代价是非常大的,它复制了父进程中的代码段、数据段和堆栈段里的大部分内容,使得fork()函数的系统开销比較大,并且运行速度页不是非常快。
exec方法
• exec 函数族提供了在一个进程中启动还有一个程序运行的方法。
• 它能够依据指定的文件名称或文件夹名找到可运行文件,并用它来代替原调用进程的数据段、代码段和堆栈段,在运行完之后,原调用进程的内容除了进程号外,其它所有被新的进程替换了。
• 可运行文件既能够是二进制文件。也能够是Linux下不论什么可运行的脚本文件。
• 什么时候使用exec
• 当进程觉得自己不能再为系统和用户做出不论什么贡献时,就能够调用 exec 函数族中的随意一个函数让自己重生
• 假设一个进程想运行还有一个程序。那么它就能够调用 fork() 函数新建一个进程。然后调用exec 函数族中的随意一个函数。这样看起来就像通过运行应用程序而产生了一个新进程
• 查找方式:表1中的前4个函数的查找方式都是完整的文件文件夹路径,而最后两个函数(也就是以p 结尾的两个函数)能够仅仅给出文件名称,系统就会自己主动依照环境变量“$PATH” 所指定的路径进行查找。
• 參数传递方式:exec函数族的參数传递有两种:一种是逐个列举的方式。而还有一种则是将全部參数总体构造指针数组传递。
在这里是以函数名的第5位字母来区分的,字母为"l"(list)的表示逐个列举參数的方式。其语法为constchar *arg;字母为“v”(vector)的表示将全部參数总体构造指针数组传递,其语法为char *const argv[]。这里的參数实际上就是用户在使用这个可运行文件时所需的全部命令选项字符串(包含该可运行程序命令本身)。
要注意的是,这些參数必须以NULL结束。
• 环境变量: exec函数族能够默认系统的环境变量,也能够传入指定的环境变量。这里以“e”(environment)结尾的两个函数execle()和execve()就能够在envp[]中指定当前进程所使用的环境变量。
exit方法
• 终止进程使用exit()和_exit()函数。当进程执行到exit()或_exit()函数时。进程会无条件的停止剩下的全部操作,清除各种数据结构。并终止本进程的执行。
• _exit()函数的作用是:直接使进程停止执行,清除其使用的内存空间,并清除其在内核中的各种数据结构;而exit()函数则在这些基础上做了一些包装,在执行退出之前加了若干道工序。
• exit()函数和_exit()函数的最大差别就在于exit()函数在终止当前进程之前要检查该进程打开过哪些文件,把文件缓冲区中的内容写回文件,也就是图1中的“清理I/O缓冲”一项。
• 在Linux的标准函数库中,有一种被称作“缓冲I/O(buffered I/O)”的操作,其特征就是相应每个打开的文件。在内存中都有一片缓冲区。
• 每次读文件时,会连续读出若干条记录,这样在下次读文件时就能够直接从内存的缓冲区中读取;相同,每次写文件时,也不过写入内存中的缓冲区,等满足了一定的条件(如达到一定数量或遇到特定字符等。最典型的就是咱们的vim中使用的:w命令),再将缓冲区中的内容一次性写入文件。
• 这样的技术大大添加了文件读写的速度,但也给咱们的编程带来了一些麻烦。比方有些数据你觉得已经被写入到文件里,实际上由于没有满足特定的条件,它们还仅仅是被保存在缓冲区内,这时用_exit()函数直接将进程关闭掉,缓冲区中的数据就会丢失。
因此,若想保证数据的完整性,最好使用exit()函数。
•
cmd命令行相关进程命令
• ps -查看系统中进程的状态
• USER表示启动进程用户
• PID表示进程标志号
• %CPU表示执行该进程占用CPU的时间与该进程总的执行时间的比例
• %MEM表示该进程占用内存和总内存的比例
• VSZ表示占用的虚拟内存大小,单位KB
• RSS为进程占用的物理内存值,单位KB
• TTY表示该进程建立时所相应的终端,假设显示“?”表示不占用终端
• START为进程開始时间
• TIME为运行的时间
• COMMAND是相应的命令名
• STAT是进程的执行状态
• D。 不可中断的睡眠
• R。 就绪(在可执行队列中)
• S, 睡眠
• T, 被跟踪或停止
• Z。 终止(僵死)的进程
• W,没有足够的内存分页可分配
• < ,高优先级的进程
• N,低优先级的进程
• L,有内存分页分配并锁在内存体内(实时系统或I/O)
• + ,前台进程
• s 。一个信息头
• l ,多线程
• 參数介绍:
-A:显示系统中全部进程的信息。
-e:显示全部进程的信息。
-f:用ASCII字符显示树状结构,表达程序间的相互关系
-l:以长格式显示进程信息。
-r:仅仅显示正在执行的进程。
-u:显示面向用户的格式(包含username、CPU及内存使用情况等信息)。
-x:显示全部非控制终端上的进程信息。
-p:显示由进程ID指定的进程的信息。
-t:显示指定终端上的进程的信息。
-H: 显示树状结构。表示程序间的相互关系
• top -显示系统当前的进程状况
• 第一行表示的项目依次为当前时间、系统启动时间、当前系统登录用户数目、平均负载。
• 第二行显示的是全部启动的、眼下执行的、挂起(Sleeping)的和僵尸(Zombie)进程。
• 第三行显示的是眼下CPU的使用情况,包含系统占用的比例、用户使用比例、闲置(Idle)比例。
• 第四行显示物理内存的使用情况,包含总的能够使用的内存、已用内存、空暇内存、缓冲区占用的内存。
• 第五行显示交换分区的使用情况,包含总的交换分区、使用的、空暇的和用于快速缓存的交换分区。
• PID(Process ID):进程标志号。是非零正整数
• USER:进程全部者的username
• PR:进程的优先级别
• NI:进程的优先级别数值
• VIRT:进程占用的虚拟内存值
• RES:进程占用的物理内存值
• SHR:进程使用的共享内存值
• STAT:进程的状态。当中S表示休眠,R表示正在执行,Z表示僵死状态,N表示该进程优先值是负数
• %CPU:该进程占用的CPU使用率
• %MEM:该进程占用的物理内存和总内存的百分比
• TIME:该进程启动后占用的总的CPU时间
• COMMAND:进程启动的启动命令名称
• 參数介绍
• d:指定更新的间隔,以秒计算。
• q:没有不论什么延迟的更新。
假设使用者有超级用户,则top命令将会以最高的优先序运行。
• c:显示进程完整的路径与名称。
• S:累积模式,会将已完毕或消失的子进程的CPU时间累积起来。
• s:安全模式。
• i:不显示不论什么闲置(Idle)或僵尸(Zombie)进程。
• n:显示更新的次数,完毕后将会退出top。