通过系统调用创建进程-fork初识创建子进程
#include
#include
pid_t fork( void)
fork有两个返回值
父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)
int main()
{
int ret = fork();
printf("hello proc : %d!, ret: %d\n", getpid(), ret);
sleep(1);
return 0;
}
主进程从main函数开始运行是一个执行分支,在fork()之后创建子进程成了两个执行分支。
#include
#include
int main(){
printf("一个分支\n");
fork();
printf("两个分支\n");
return 0;
}
include<stdio.h>
#include
int main(){
printf("一个分支\n");
pid_t ret=fork();
printf("pid:%d,ppid:%d,ret:%d\n",getpid(),getppid(),ret);
printf("两个分支\n");
return 0;
}
fork 之后通常要用if 进行分流
#include
#include
#include
int main()
{
int ret = fork();
if(ret < 0){
perror("fork");
return 1;
}
else if(ret == 0){ //child
printf("I am child : %d!, ret: %d\n", getpid(), ret);
}else{ //father
printf("I am father : %d!, ret: %d\n", getpid(), ret);
}
sleep(1);
return 0;
}
创建子进程fork()函数给父进程返回的的是子进程pid所以执行的是else语句给子进程返回的是0所i执行的是第二个分支
1 如何理解创建进程?
创建进程,是系统多了一个进程,多了一个进程系统就要多一组管理进程的数据结构+该进程对应的数据和代码
2 fork()为什么会有两个返回值?
fork函数的return语句父进程执行,子进程也要执行,函数的返回值是数据,各自私有一封
3 fork父子执行顺序和代码和数据复制的问题
进程数据=代码+数据
父进程创建子进程的时候吗,代码是共享的,数据是各自私有一份(写实拷贝)。通过数据私有表现进程的独立性
代码是逻辑一般不可修改
数据是可以修改
4 为何给父进程返回子进程的pid,给子进程返回0
进程状态
看看Linux内核源代码怎么说
为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在
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 | ps axj 命令
为什么要有僵尸状态?
保持进程基本退出信息,方便父进程读取,获取退出原因
进程死亡,父进程(系统调用,os,检测进程运行完的时候,结束情况,(1 是否正常结束 2 是否异常 3 发生了什么异常))
有什么特征?
一般僵尸进程,task_struct是会被保留下来,进程的退出信息,是放在进程控制快中。
僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)
没有读取到子进程退出的返回代码时就会产生僵死(尸)进程 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
#include
#include
int main()
{
pid_t id = fork();
if(id < 0){
perror("fork");
return 1;
}
else if(id > 0){ //parent
printf("parent[%d] is sleeping...\n", getpid());
sleep(30);
}else{
printf("child[%d] is begin Z...\n", getpid());
sleep(5);
exit(EXIT_SUCCESS);
}
return 0;
}
孤儿进程
#include
#include
int main()
{
pid_t id = fork();
if(id < 0){
perror("fork");
return 1;
}
else if(id > 0){ //parent
printf("parent[%d] is sleeping...\n", getpid());
sleep(30);
}else{
printf("child[%d] is begin Z...\n", getpid());
sleep(5);
exit(EXIT_SUCCESS);
}
return 0;
}
如果父进程没有父进程,但是该进程退出,进入僵尸,该进程的资源没有办法被回收,内存泄漏.
os考虑了这个问题,孤儿进程,是要被领养的,os,1号进程领养
进程优先级
cpu资源分配的先后顺序,就是指进程的优先权(priority)。
优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整
体性能。
在linux或者unix系统中,用ps –l命令则会类似输出以下几个内容
优先级:pri ,ni(nice优先级修正数据)
优先级=pri_old+nice
UID : 代表执行者的身份
PID : 代表这个进程的代号
PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
PRI :代表这个进程可被执行的优先级,其值越小越早被执行
NI :代表这个进程的nice值
PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小
进程的优先级别越高
那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值
PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice
这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行
所以,调整进程优先级,在Linux下,就是调整进程nice值
nice其取值范围是-20至19,一共40个级别。
查看进程优先级的命令
ps -al
用top命令更改已存在进程的nice:
例子:
输入top打开top页面
按r接着输入要修该优先级的进程的pid号输入3115
接着输入要修改nice的值回车修改
竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高
效完成任务,更合理竞争相关资源,便具有了优先级
独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为
并发
环境变量
执行一条命令:1 找到这条命令 2 运行它
./a.out:目的是找到a.out程序
ls 一定有它默认查找路径!Path环境变量中,环境变量也是变量(变量名Path+变量内容(路径))
是什么?
系统中的某些具有一定全局性质的变量,通常是为了满足摹写系统要求
为什么?
系统的全局变量,都是为了方便用户,系统进行的最简单化的查找,定位
怎么办?
env:显示所有环境变量
export导出环境变量
还有其他常见的环境变量PAth SHELL HOME
框中为命令行参数 ls为可执行程序
int main(int argc ,char *argv,char*env[]){
return 0
}