操作系统为每个进程分配一个独一无二的数字编号,这个编号称为进程标识符
正整数[ 2 - cat/proc/sys/kernel/pid_max ) 操作系统选择下一个没有被使用的编号作为进程编号
0--内核进程
1--由0号进程产生,第一个用户态进程
进程创建的一般过程
1.给新进分配一个标识符。在内核中分配一个PCB2.复制父进程的环境(PCB中的信息)
3.分配资源(程序,数据,栈,地址空间等)
4.复制父进程地址空间的内容。
5.将进程置成就绪状态,放入就绪队列
pid_t fork(void) //创建进程
1.功能:创建子进程
2.返回:失败返回-1, 成功,父进程返回子进程id,子进程返回0;
3.调用fork之后通常要用if进行分流
fork()注意:
1.调用fork后, 父子进程交替运行,
2.如果父进程先死,子进程变为孤儿进程,,孤儿进程会被1号进程收养
3.如果子进程先死,就会变成僵尸进程。 处理僵尸进程-----结束父进程
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
pid_t pid;
printf("before fork: %d\n", getpid());
pid = fork();
if(pid == -1) {
fprintf(stderr, "fork err\n");
exit(1);
}
if(pid == 0){
printf("this is child, myid = %d, parentid = %d\n", getpid(), getppid());
sleep(1);
}
else if(pid > 0){
printf("this is parent, myid = %d, mychildid is %d\n", getpid(), pid);
sleep(1);
}
printf("finish\n");
}
子进程继承父进程的那些东西?
1.地址空间2.进程上下文(除PCB外的)
3.进程堆栈 写时拷贝
4.内存信息
5.文件描述符 --- 父进程打开的文件也要继承
6.信号设置情况
7.父进程的调度优先级 缺省为0 , -20 到 19 nice renice修正
8.当前路径
9.根路径
10.控制终端
11.进程组 --- 父进程和子进程缺省为同一进程组
12.资源限制
哪些不继承?
父进程的锁子进程不继承
父进程ID子进程不继承
父进程未决的信号,子进程清除掉
孤儿进程:
一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被1号init进程所收养,
并由该1号进程对它们完成回收工作。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有获取子进程的状态信息,那么子进程的进程描述符仍然保存在
系统中,并会一直等待父进程读取退出状态码。这种进程称之为僵死进程。
危害:
状态僵尸进程一直保持在Z状态不退出,系统就一直要维护僵尸进程的PCB(进程的退出状态),造成系统资源的浪费。
前面我们知道系统会为每个进程分配一个进程标识符,进程标识符是有限的,当僵尸进程过多时,会导致进程标识符无法分配。
父进程创建了大量的子进程而不进行回收,就会造成内存内存泄漏。
孤儿进程最后会由init进程接管,所以造成的危害较小。
env 查看所有环境变量
在父bash定义的变量 ,在子bash无法使用
本地变量:只能在本进程使用, aaa = 'hehe'
环境变量:本进程和子进程都能使用 export aaa 把aaa设置成环境变量
子进程定义的环境变量父进程无法使用
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
putenv("c=czf"); //增加或修改环境变量
pid_t pid;
pid = fork();
if(pid == 0){
printf("child %s\n", getenv("c")); //取得环境变量的内容
}else if(pid > 0){
printf("parent %s\n", getenv("c"));
}
return 0;
}
进程优先级:
CPU资源分配的先后顺序,即进程的优先权。
优先权高的优先执行。配置进程优先级可以有效系统性能。
启动前调整:nice
nice -n -5 ./a.out
调整已存在的进程优先级:renice
renice -5 -p 1234 //1234为进程的pid
top命令:
进入top -> 按r ->输入pid ->输入nice值