1.进程定义:一个其中运行着一个或多个线程的地址空间和这些线程所需要的系统资源。
2.程序代码和系统函数会共享在进程之间,任何时候都在内存中只有一份副本哦。
3.进程号0-32768的整数,当新进程启动了,就自动选下一个没有被分配的PID做为id号。当数字回绕一圈时,新进程就从2开始,1是为init所独有的哦。
4.进程有独立的堆栈空间和独立的环境空间:包含专门为这个进程建立的环境变量。putenv getenv,还有自己必须维护的程序计数器,用来记录代码执行到了那个位置了。
5.linux中有进程表:用来记录所有的进程信息。PID就是索引。进程表长度是有内存容量限制的,所以系统运行的进程数量也是有上限的。 ps -a all ; ps -f ; full 完整
6.进程状态:S 睡眠 R 运行 D 等待用户输入或输出 T 停止 Z 死进程僵尸 N 低优先级 <高优先级 l 进程是多线程的 s 进程是会话期首进程。 + 进程属于前台进程组 W分页
7.init 进程是:系统第一个进程。可以说是进程管理器。祖先进程。 启动新进程并等待他们结束的能力是整个系统的基础:我们调用fork exec wait来完成同样的任务。
8.每个进程轮到的运行时间称之为:时间片。so ,it looks like so match 进程在同时运行。系统内核用进程调度器来决定下一个时间片应该分配给那一个进程。依据优先级。
9.表现良好的程序成为:nice程序。 系统根据进程的nice值来决定他的优先级,一个进程的nice值默认为0,并根据其运行的表现而变化。一般,长期不间断运行的程序,nice值会比较低。而需要等待用户输入的程序系统会增加其nice值。 我们可以使用Nice命令,设置进程nice值,renice命令调整nice值。 ps -l or -f
renice 10 pid ; 调整nice值为0。高优先级的进程总是运行的更频繁,甚至在有些系统中:只要还有高优先级的进程可以运行,那么低优先级的进程根本就不能运行。
10.启动新进程: system() #include <stdlib.h> int main(){ begin: system(" ls -l & "); end; } 其调用shell来启动程序。
system:其缺点是:程序必须等待由system函数启动的进程结束之后才能继续,因此我们不能立刻执行其他任务。(很少使用system,因为他依赖于shell)
1.exec系类函数:使用exec启动新的程序,原来的程序就不再运行了。 l : 使用可变参数。 v:使用数组。出错返回-1,否则不反悔,因为没了嘛。(替换了都)
int execl( const char *path , const char *arg0...,(char*) 0); //直接给定了程序路径。
int execlp (const char *file , const char *arg0, ... ,(char* ) 0 ); //通过搜索环境路径来找到这个程序 //在系统默认path中去找。
int execle(const char *path , const char *arg0,... , (char*)0 , char *const envp[] ); //这里最后一个参数是:心程序的环境变量数组。main的隐士最后一个形参呗。
-----------以下和以上一致,只是传递给main的参数使用数组来传递。
int execv(...) ;
int execvp(...); char* const ps_argv[]={ "ps", "ax" , 0 }; //参数数组这样设置滴。
int execve(.....); char *const ps_envp[] = { " PATH=/bin:/usr/bin" , "TERM=console" , 0 }; //环境数组这样设置滴。
例子: #include <unistd.h> int main(){ execl( "/bin/ps" ,"ps","ax",0); } 注意哦,第一个参数依旧是那个程序名称哦,
2.想让进程执行多个函数:我们可以使用多线程、也可以创建一个完全新的进程(fork ,像init的做法一样)。
3.使用fork创建出来的新进程和原来的一模一样,只是具有自己的数据空间等罢了。其执行位置都是一样的。#include <sys/types.h> <unistd.h> pid_t fork();
4.fork出来的新进程,返回值是0,以区别父子进程。 0 是儿子。 失败 返回-1 : 子进程数目达到上限 or 没有了足够的空间来创建进程。
5. #include <sys/types.h> <unistd.h> <stdio.h> main: pid_t newpid = fork(); switch(newpid) { case -1: error ; break; case 0 : son is me ;break; default : father is me ;break;} 其返回值是:pid_t 类型: <sys/types.h> 中。 我们可以通过sleep(1) 来使进程间切换。
6.wait() 我们可以通过wait() 函数来使一个进程等待另一个进程的结束。#include <sys/wait.h> <sys/types.h> pid_t wait( int *stat_loc); 返回已经结束的那个进程的pid.
如果参数 stat_loc不是空指针,那么,该结束的进程的结束状态信息会写入到stat_loc 所指向的内存中:正常结束,非正常结束,等等。。
错误状态信息:#include <sys/wait.h> 中定义了这些宏。
WIFEXITED(stat_val) : 如果子进程正常结束,它就取一个非0值。
WEXITSTATUS(stat_val) : 如果WIFEXITED(stat_val) 非0,它返回子进程的退出码。
WIFSIGNALED(stat_val) : 如果子进程因为一个未捕获的信号而终止,他就取一个非0值。
WTERMSIG(stat_val) : 如果 WIFSIGNALED(stat_val) 非0,他返回一个信号代码。
WIFSTOPPED(stat_val) : 如果子进程意外终止,他就取一个非0值。
WSTOPSIG(stat_val) : 如果WIFSTOPPED非0 ,他返回一个信号代码。
我明白了:所谓的等待:就是等那个进程运行结束了,你才结束。 是在调用wait()那一刻。才开始等待,之前不等待。wait()的时候,那个进程是阻塞在那里的。
有没有子等父这一说呢?wait() 函数是用于父等子的。