方式一: 使用system函数
特点: 当进程被创建之后,当前进程不再执行(处于挂起状态)
待被创建进程执行结束之后当前进程继续执行
被创建程序代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
printf("先休息再工作\n");
sleep(5);
for (int i = 0; i < 5; ++i)
{
printf("子进程pid:%d\n",getpid());
}
return 0;
}
运行结果:
创建子进程的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
printf("先睡为敬!\n");
sleep(3);
printf("睡完了,干活儿!\n");
system("./test.exe");
printf("活儿干完了,继续睡!\n");
sleep(5);
printf("睡醒了,干饭,干饭\n");
return 0;
}
运行结果:
方式二: 使用fork函数或vfork函数
特点: 如果当前进程为父进程,那么当父进程创建子进程之后,父子进程同时执行
fork函数创建子进程,子进程以拷贝父进程全部代码的方式来创建子进程并记录父进程的上下文(父进程运行到的位置), 父进程与子进程依据fork函数的返回值来区分
父进程fork函数返回子进程pid, 子进程fork函数返回0
代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
printf("这是父进程,父进程id:%d\n",getpid());
sleep(3);
printf("开始创建子进程--->\n");
int ret = fork();
int n = 0;
if(ret){
//父进程
printf("这是父进程pid:%d\tret:%d\n",getpid(),ret);
while(1){
printf("父n-->:%d\n",n++);
sleep(3);
}
}else{
//子进程
printf("这是子进程pid:%d\tret:%d\n",getpid(),ret);
while(1){
printf("子n-->:%d\n",n+=2);
sleep(3);
}
}
return 0;
}
结果:
示例: 父进程打印当前时间,子进程打印随机数
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
int main(){
char userName[25]="student";
char passWord[25]="123456";
char user[25];
char pass[25];
while(1){
printf("请输入用户名:");
scanf("%s",user);
printf("请输入密码:");
scanf("%s",pass);
if(0 == strcmp(user,userName) &&
0 == strcmp(pass,passWord)){
printf("登录成功!\n");
break;
}else{
printf("输入错误,请重新输入!\n");
sleep(2);
system("clear");
}
}
int ret = fork();
if(ret){
//父进程打印当前时间
struct tm* pt = NULL;
time_t tt;
while(1){
tt = time(NULL);
pt = localtime(&tt);
printf("时间: %02d:%02d:%02d\n",
pt->tm_hour,pt->tm_min,pt->tm_sec);
//间隔一秒循环一次
sleep(1);
}
}else{
//子进程打印随机数
srand((unsigned int)time(NULL));
while(1){
printf("随机数----->%d\n",rand()%10000000);
//间隔半秒循环一次
usleep(500000);
}
}
return 0;
}
结果:
由此可以说明,子进程与父进程是同时运行的
方式三: 使用exec簇
exec 族函数的特征:调用 exec 族函数会把新的程序装载到当前进程中. 在调用过 exec 族函数后,进程中执行的代码就与之前完全不同了,所以 exec 函数调用之后的代码是不会被执行的