进程的状态
O:就绪态,一切准备工作都已经做好,等待被调用。
R:运行态,Linux下没有就绪态,O也就是R。
S:可唤醒的睡眠态,系统调用、获取到资源、收到信息都可以被唤醒。
D:不可唤醒的睡眠态,必须等到的事件发生。
T:暂停态,收到了SIGSTOP信号,当收到SIGCONT信号则继续运行。
X:死亡态。
Z:僵尸态。
<:高优先级。
N:低优先级。
L:多线程进程。
s:有子进程的进程。
+:后台进程组。
ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 126212 4296 ? Ss Sep14 0:19 /usr/lib/systemd/systemd --switched
root 2 0.0 0.0 0 0 ? S Sep14 0:00 [kthreadd]
可以通过ps的命令来看到进程的状态:STAT
一个进程可以拥有多种状态。
fork
pid_t fork(void);
功能:创建子进程
1、失败返回-1,如果成功会返回两次。
2、父进程会返回子进程的id,子进程返回0
3、根据返回值的不同,分别为子进程和父进程设计不同的分支。
4、通过fork创建出的子进程,就是父进程的副本,它会把父进程的堆、栈、全局段、静态数据段、IO流的缓冲区都拷贝一份,父子进程共享代码段。
5、fork函数调用成功后,父子进程就开始各自执行了,它们的先后顺序是不确定的,但可以通过某些实现来保证。
#include <stdio.h>
#include <unistd.h>
int main()
{
if(fork())
{
printf("进程id:%d 父进程id:%d\n", getpid(), getppid());
while(1);
}
if(fork())
{
printf("进程id:%d 父进程id:%d\n", getpid(),getppid());
while(1);
}
if(fork())
{
printf("进程id:%d 父进程id:%d\n", getpid(), getppid());
while(1);
}
printf("进程id:%d 父进程id:%d\n", getpid(), getppid());
while(1);
}
输出结果:
进程id:26146 父进程id:4594
进程id:26147 父进程id:26146
进程id:26148 父进程id:26147
进程id:26149 父进程id:26148
6、当总进程数超过系统的限制时,就无法再创建进程的了,此时fork函数会返回-1,执行失败。
7、孤儿进程:子进程还有运行,但父进程已经结束,此时子进程会被init(1)收养,子进程变成孤儿进程。
#include <stdio.h>
#include <unistd.h>
int main()
{
int pid = fork();
if(pid == 0)
{
printf("子进程:%d 父进程%d\n", getpid(), getppid());
sleep(2);
printf("子进程:%d 父进程%d\n", getpid(), getppid());
}
sleep(1);
return;
}
输出结果:
子进程:28010 父进程28009
子进程:28010 父进程1 // 此时父进程已消亡 子进程被init(1)收养 成为孤儿进程
8、僵尸进程:子进程已经死亡,但父进程没有及时回收子进程,此时子进程就会变成僵尸进程。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int pid = fork();
if(pid == 0)
{
printf("子进程:%d\n", getpid());
exit(0);
}
while(1);
}
输出结果:
子进程:29928
通过ps命令查看子进程:29928状态:已经是Z表示僵尸进程。
29928 0.0 0.0 0 0 pts/0 Z+ 19:45 0:00 [a.out] <defunct>
9、父进程打开的文件和子进程是共享的。