sleep()函数
sleep函数的作用就休眠指定的秒数,休眠期间让出CPU,其它进程可以执行。
下面示例一和示例二的区别就是,前者有sleep函数,在父进程进行休眠的时候让出了cpu,此时子进程可以执行了,从而达到了交替睡眠,交替执行的目的
后者是注释了sleep函数所以,父进程在执行完自己的进程之后才让出cpu让子进程来执行
示例一:
#include <unistd.h>
#include <stdio.h>
#include<sys/types.h>
int main()
{
int p1,i;
while ((p1=fork())==-1);//负数:如果出错,则fork()返回-1,此时没有创建新的进程。最初的进程仍然循环运行。
if (p1>0)
for (i=0;i<5;i++)
{
printf("I am parent %d.
",i);
sleep(1);
}
else
for (i=0;i<5;i++)
{
printf("I am child %d.
",i);
sleep(1);
}
return 0;
}
/*
执行结果:
slee@s-magicbook:~/s_code$ ./shiyan2_0
I am parent 0.
I am child 0.
I am parent 1.
I am child 1.
I am parent 2.
I am child 2.
I am parent 3.
I am child 3.
I am child 4.
I am parent 4.
*/
示例二
#include <unistd.h>
#include <stdio.h>
#include<sys/types.h>
int main()
{
int p1,i;
while ((p1=fork())==-1);//负数:如果出错,则fork()返回-1,此时没有创建新的进程。最初的进程仍然循环运行。
if (p1>0)
for (i=0;i<5;i++)
{
printf("I am parent %d.
",i);
//sleep(1);
}
else
for (i=0;i<5;i++)
{
printf("I am child %d.
",i);
//sleep(1);
}
return 0;
}
/*
执行结果:
slee@s-magicbook:~/s_code$ ./shiyan2_0
I am parent 0.
I am parent 1.
I am parent 2.
I am parent 3.
I am parent 4.
I am child 0.
I am child 1.
I am child 2.
I am child 3.
I am child 4.
*/
exit系统调用:
exit这个系统调用是用来终止一个进程的。无论在程序中的什么位置,只要执行到exit系统调用,进程就会停止剩下的所有操作,清除包括PCB在内的各种数据结构,并终止本进程的运行。
示例
#include<stdlib.h>
#include<stdio.h>
int main()
{
printf("this process will exit!
");
exit(0);
printf("never be displayed!
");
}
/*
执行结果:
slee@s-magicbook:~/s_code$ ./shiyan2_0
this process will exit!
*/
never be displayed!没有输出是因为遇到进程遇到exit就戛然而止了
wait函数
进程一旦调用了wait,就立即阻塞自己,由wait自动分析当前进程的某个子进程是否已经退出,如果让它找到了这样一个已经变成僵尸的子进程, wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。pid = wait(NULL); 如果成功,wait会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用就会失败,此时wait返回-1。
函数原型
pid_t wait (int * status);
函数说明
参数 status 是一个整形指针。如果status不是一个空指针,则终止进程的终止状态将存储在该指针所指向的内存单元中。如果不关心终止状态,可以将 status参数设置为NULL。
status 不是NULL时子进程的结束状态值会由参数 status 返回,而子进程的进程识别码作为函数返回值返回。
调用 wait 函数时,调用进程将会出现下面的情况:
- 如果其所有子进程都还在运行,则阻塞。
- 如果一个子进程已经终止,正等待父进程获取其终止状态,则获取该子进程的终止状态然后立即返回。
- 如果没有任何子进程,则立即出错返回。
返回值
如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。
需要都头文件
#include <sys/types.h> #include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include <sys/wait.h>
int main()
{
pid_t j,p1,i;
while ((p1=fork())==-1);
if (p1>0)
{
wait(0);//这里不用返回值,直接调用就可以阻塞本进程
for (i=0;i<5;i++)
{
printf("I am parent %d.
",i);
sleep(1);
}
}else{
for (i=0;i<5;i++)
{
printf("I am child %d.
",i);
sleep(1);
}
exit(0);
}
return 0;
}
/*执行结果:
slee@s-magicbook:~/s_code$ gcc -o shiyan2_0 shiyan2_0.c
slee@s-magicbook:~/s_code$ ./shiyan2_0
I am child 0.
I am child 1.
I am child 2.
I am child 3.
I am child 4.
I am parent 0.
I am parent 1.
I am parent 2.
I am parent 3.
I am parent 4.
如果把wait(0)注释了就会出现下面的结果:
slee@s-magicbook:~/s_code$ gcc -o shiyan2_0 shiyan2_0.c
slee@s-magicbook:~/s_code$ ./shiyan2_0
I am parent 0.
I am child 0.
I am parent 1.
I am child 1.
I am parent 2.
I am child 2.
I am parent 3.
I am child 3.
I am child 4.
I am parent 4.
*/
exit和sleep的配合构造僵尸进程
在一个进程调用了exit之后,该进程并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构。在Linux进程的5种状态中,僵尸进程是非常特殊的一种,它已经放弃了几乎所有内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态等信息供其他进程收集。sleep的作用是让进程休眠指定的秒数,在子进程已经退出,而父进程正忙着睡觉,不可能对它进行收集,这样,就能保持子进程10秒的僵尸状态。
#include<stdlib.h>
#include<sys/wait.h>
#include <stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{ pid_t pid ,pr;
pid=fork();
while( pid <0);
if(pid == 0 ){
printf("this is child process with pid of %d
",getpid());
exit(0);
}
else{
sleep(10);
pr=wait(NULL);//pr是子进程的号
printf("I catch a child process with pid of %d
",pr);
}
}
/*
执行结果:
slee@s-magicbook:~/s_code$ gcc -o shiyan2_0 shiyan2_0.c
slee@s-magicbook:~/s_code$ ./shiyan2_0
this is child process with pid of 3936
I catch a child process with pid of 3936
*/
综合练习:
实现三个进程并行
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
int main(){
int pid1, pid2, i=1;
while ( (pid1=fork()) ==-1);//fork一个子进程1
if (pid1==0) {
printf ("This is child process 1, pid=%d
",getpid() ) ;
sleep (1) ;
for (i='A' ;i<='Z' ; i++) {
printf ("Child process1 print %c
",i );
sleep (1) ;
}
exit (0) ;
} else{ //对于父进程main
while ( (pid2=fork()) ==-1) ; //再fork一个子进程2
if (pid2==0) {
printf ("This is child process 2, pid=%d
", getpid() ) ;
sleep (1) ;
for (i='a' ; i<='z' ; i++) {
printf ("Child process2 print :%c
", i) ;
sleep (1) ;
}
exit (0) ;
} else {
printf ("This is a parent process, pid=%d
", getpid()) ;
sleep (1) ;
for (i=1; i<=26; i++) {
printf ("Parent process print :%d
", i) ;
sleep (1) ;
}
exit (0) ;
}
}
}
/*
执行结果:
slee@s-magicbook:~/s_code$ gcc -o shiyan2_0 shiyan2_0.c
slee@s-magicbook:~/s_code$ ./shiyan2_0
This is child process 1, pid=5025
This is a parent process, pid=5024
This is child process 2, pid=5026
Child process1 print A
Parent process print :1
Child process2 print :a
Parent process print :2
Child process1 print B
Child process2 print :b
Parent process print :3
Child process1 print C
Child process2 print :c
Parent process print :4
Child process1 print D
Child process2 print :d
Parent process print :5
Child process1 print E
Child process2 print :e
Parent process print :6
Child process1 print F
Child process2 print :f
Child process1 print G
Parent process print :7
Child process2 print :g
Child process1 print H
Parent process print :8
Child process2 print :h
Child process1 print I
Parent process print :9
Child process2 print :i
Child process2 print :j
Child process1 print J
Parent process print :10
Child process2 print :k
Child process1 print K
Parent process print :11
Child process1 print L
Child process2 print :l
Parent process print :12
Child process1 print M
Child process2 print :m
Parent process print :13
Child process1 print N
Parent process print :14
Child process2 print :n
Child process1 print O
Child process2 print :o
Parent process print :15
Child process1 print P
Child process2 print :p
Parent process print :16
Child process1 print Q
Parent process print :17
Child process2 print :q
Child process1 print R
Child process2 print :r
Parent process print :18
Child process1 print S
Child process2 print :s
Parent process print :19
Child process1 print T
Child process2 print :t
Parent process print :20
Child process1 print U
Parent process print :21
Child process2 print :u
Child process2 print :v
Child process1 print V
Parent process print :22
Parent process print :23
Child process1 print W
Child process2 print :w
Child process1 print X
Parent process print :24
Child process2 print :x
Parent process print :25
Child process1 print Y
Child process2 print :y
Child process1 print Z
Parent process print :26
Child process2 print :z
*/