1.进程概念
进程是一个具有独立功能的程序的一次动态执行过程,简单的说,进程就是正在执行的程序。进程与程序不同,程序是永久的,静态的,而进程是暂时的,动态的。一个程序可以多次加载到内存中成为多个进程。
linux中的进程都由其它进程所创建(除了pid为0号的idle进程),创建新进程的进程叫父进程,新进程叫子进程。
2.进程的标识
在linux系统中,最重要的进程标识是进程号(Process Idenity Number,PID)。PID能唯一标识一个进程,PID是一个非零正整数。
获取当前进程PID的函数:pid_t getpid(void);
获取当前进程的父进程PID的函数 pid_t getppid(void);
测试代码:
#include<stdio.h>
#include<unistd.h>
int main(void)
{
printf("PID = %d \n",getpid());//打印进程PID
printf("PPID = %d\n",getppid());//打印父进程PID
return 0;
}
测试结果:
可以看到,该进程ID为3741,其父进程ID为2818
3.创建进程
创建新进程的函数为fork(),其函数原型为:
pid_t fork(void);
fork函数调用进程失败会返回-1,调用成功会返回两次:在父进程中返回子进程的PID,在子进程中返回0。执行fork后,子进程和父进程将具有相同的程序和数据。
测试代码:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int a=0;
int main(void)
{
int b=0;
int pid=0;
a++;
b++;
printf("a=%d,b=%d\n",a,b);
pid=fork();
a++;
b++;
printf("a=%d,b=%d\n",a,b);
printf("pid=%d\n",pid);
return 0;
}
测试结果:
可以看到,在执行fork后,父子进程打印的a,b值相同,说明两个进程有各自的数据区和用户堆栈。
4.进程控制
调用fork函数,子进程与父进程执行的程序相同,为了使子进程执行不同的函数,需要调用exec函数,调用该函数后该进程的用户空间代码和数据完全被新程序替换掉,从而让子进程成为一个真正的新进程。exec函数包括6种以exec开头的函数:
int execl(const char* path, const char* arg, ...);
int execlp(const char* file, const char* arg, ...);
int execle(const char* path, const char* arg, ..., char* const envp[]);
int execv(const char* path, const char* argv[]);
int execvp(const char* file, const char* argv[]);
int execve(const char* path, const char* argv[], char* const envp[]);
参数path为可执行文件路径,argv为命令行参数。参数列表的最后必须以NULL结束。
测试代码:
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int pid;
pid=fork();
if(pid==0)//子进程中执行hello
{
execv("./hello",NULL);
}
else//父进程中打印子进程PID
{
printf("PID of new process is :%d\n",pid);
}
return 0;
}
运行结果:
新建进程的PID为3949,在新进程中执行了hello程序,并打印出了“hello,world”字符串。
5.system函数
system函数可以在一个程序的内部启动另一个程序,从而创建一个新进程。system函数需要的头文件为:#include<stdlib.h>,函数原型为:
int system(const char *string);
string是包含了命令的字符串,该函数能执行命令。
测试代码:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
system("pwd");
system(" ls -l");
printf("OK!\n");
return 0;
}
运行结果:
可以看到该程序成功打印了当前工作目录和目录下的文件,因此,借助system函数我们能很方便的执行命令行程序。
6.应用示例
设已有一个hello.c程序,该程序输出“hello,world!”,现在编写一个程序来编译该源程序,编译完成后执行该程序。
示例代码:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main(void)
{
system("gcc hello.c -o hello");
printf("hello.c compile sucessfully!\n");
if(fork()==0)
{
if(execlp("./hello","hello",NULL)<0)
{
printf("execlp error!\n");
}
}
sleep(1);
printf("Hello run successfully!\n");
return 0;
}
运行结果: