linux进程相关api

文章目录

  • 创建进程
    • 替换进程映像
    • 复制进程映像
  • 等待进程

创建进程

替换进程映像

exec系列函数可以创建(启动)新进程,并替换原进程的进程映像。exec系列函数如下所示:

#include 
int execl(const char *path, const char *arg, ...,(char  *) NULL);
int execlp(const char *file, const char *arg, ...,(char  *) NULL);
int execle(const char *path, const char *arg, ..., (char *) NULL, char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);

这些函数按参数个数是否可变,可以分为两类。
①execl()、execlp()、execle(),他们的特点是:
1)参数个数可变;
2)最后一个arg参数为(char *) NULL。
3)函数名中带字母“l”。

②execv()、execp()、execvp(),他们的特点是:
1)参数个数不可变;
2)第二个参数是一个字符串数组,数组的最后一个元素需是(char *) NULL。
3)函数名中带字母“v”。

按第一个参数的类型,可以分为两类。
①execlp()、execvp()、execvpe(),他们的特点是:
1)第一个参数名为“file”;
2)第一个参数为被调用(启动)的可执行文件名,函数会通过PATH环境变量搜索该可执行文件,如果该文件不在PATH定义的路径中,则需要使用全路径名。
3)函数名中带字母“p”,表是可以通过PATH环境变量搜索。

②execl()、execle()、execv(),他们的特点是:
1)第一个参数名为“path”;
2)第一个参数为被调用(启动)的可执行文件的路径名,无论PATH环境变量是否包含该可执行文件的路径。
3)函数名中不带字母“p”,表是不可以通过PATH环境变量搜索

示例1:

#include 
#include 
void exec1()
{	
	printf("enter exec1\n");
	const char *path = "/bin/ps";//此处需要使用路径名
	const char *arg = "ps";
	const char *arg1 = "";
	execl(path,arg, (char	*) NULL);
	printf("leave exec1\n");
}
void main()
{
	printf("enter main\n");
	exec1();
	printf("leave main\n");
}

打印结果:

enter main
enter exec1
   PID TTY          TIME CMD
 10305 pts/18   00:00:00 bash
 11156 pts/18   00:00:00 ps

分析:函数execl执行成功之后原进程映像被“ps”程序替换,故原进程中的

printf("leave exec1\n");
printf("leave main\n");

这两句为执行。

示例2:

#include 
#include 
void exec2()
{	
	printf("enter exec2\n");
	const char *file = "ps";//此处使用可执行文件名
	const char *arg = "ps";
	const char *arg1 = "";
	execlp(file,arg, (char	*) NULL);
	printf("leave exec2\n");
}
void main()
{
	printf("enter main\n");
	exec2();
	printf("leave main\n");
}

打印结果:

enter main
enter exec2
   PID TTY          TIME CMD
 10305 pts/18   00:00:00 bash
 11202 pts/18   00:00:00 ps

分析:函数execlp执行成功之后原进程映像被“ps”程序替换,故原进程中的

printf("leave exec2\n");
printf("leave main\n");

这两句为执行。

示例3:

#include 
#include 
void exec3()
{	
	printf("enter exec3\n");
	const char *path = "/bin/ps";
	const char *arg = "ps";
	const char *arg1 = "";
	char * const envp[] = {"/bin:/usr/bin",NULL};//此处环境变量参数可有可无。
	execle(path,arg, (char	*) NULL,NULL);
	printf("leave exec3\n");
}
void main()
{
	printf("enter main\n");
	exec3();
	printf("leave main\n");
}

打印结果:

enter main
enter exec3
   PID TTY          TIME CMD
 10305 pts/18   00:00:00 bash
 11216 pts/18   00:00:00 ps

分析:函数execle执行成功之后原进程映像被“ps”程序替换,故原进程中的

printf("leave exec3\n");
printf("leave main\n");

这两句为执行。

示例4:

#include 
#include 
void exec4()
{	
	printf("enter exec4\n");
	const char *path = "ps";//"/bin/ps"
	char *const argv[] = {"ps",NULL};
	execv(path,argv);
	printf("leave exec4\n");
}
void main()
{
	printf("enter main\n");
	exec4();
	printf("leave main\n");
}

打印结果:

enter main
enter exec4
leave exec4
leave main

分析:由于函数execv第一个参数未使用路径名,故execv执行失败,创开启新进程。

示例5:

#include 
#include 
void exec5()
{	
	printf("enter exec5\n");
	const char *file = "ps";
	char *const argv[] = {"ps",NULL};
	execvp(file,argv);
	printf("leave exec5\n");
}
void main()
{
	printf("enter main\n");
	exec5();
	printf("leave main\n");
}

打印结果:

enter main
enter exec5
   PID TTY          TIME CMD
 10305 pts/18   00:00:00 bash
 11246 pts/18   00:00:00 ps

分析:函数execvp执行成功之后原进程映像被“ps”程序替换,故原进程中的

printf("leave exec5\n");
printf("leave main\n");

这两句为执行。

示例6:

#include 
#include 
void exec6()
{	
	printf("enter exec6\n");
	const char *file = "ps";
	char *const argv[] = {"ps",NULL};
	char * const envp[] = {"/bin:/usr/bin",NULL};
	execvpe(file,argv,envp);
	printf("leave exec6\n");
}
void main()
{
	printf("enter main\n");
	exec6();
	printf("leave main\n");
}

打印结果:

enter main
enter exec6
   PID TTY          TIME CMD
 10305 pts/18   00:00:00 bash
 11258 pts/18   00:00:00 ps

分析:函数execvpe执行成功之后原进程映像被“ps”程序替换,故原进程中的

printf("leave exec6\n");
printf("leave main\n");

这两句为执行。

复制进程映像

如果想要进程同时执行多个函数,可以调用fork函数创建一个与原进程完全分离的进程。这个系统调用复制当前进程,并在进程表中创建一个新的表项,该表项与原进程表项基本相同。新进程与原进程几乎一模一样,执行的代码也完全相同,但新进程有自己独立的数据空间、环境和文件描述符。fork函数的部分manual如下所示:

NAME
       fork - create a child process
SYNOPSIS
       #include 
       pid_t fork(void);
RETURN VALUE
       On success, the PID of the child process is returned in the parent, and
       0 is returned in the child.  On failure, -1 is returned in the  parent,
       no child process is created, and errno is set appropriately.

fork用法介绍

  • fork函数执行成功后会复制一份当前进程(父进程)的进程映像,即子进程。此时子进程的PID会返回给父进程,“0”会返回给子进程。
  • fork函数执行失败则返回“-1”给父进程。
    用法示例
#include 
#include 

int main()
{
	pid_t pid;
	pid = fork();
	if(pid == -1){
		printf("fork failed\n");
		return 1;
	}else if(pid){
		printf("The father return value is %d\n",pid);
		printf("The father pid is %d\n",getpid());		//获取进程id
		printf("The father ppid is %d\n",getppid());	//获取父进程id
		while(1);
	}else{
		printf("The child return value is %d\n",pid);
		printf("The child pid is %d\n",getpid());	//获取进程id
		printf("The child ppid is %d\n",getppid());	//获取父进程id
		while(1);
	}
	return 0;
}
The father return value is 12002
The father pid is 12001
The father ppid is 10305
The child return value is 0
The child pid is 12002
The child ppid is 12001

等待进程

系统调用wait可以挂起父进程,等待子进程结束。

NAME
       wait, waitpid, waitid - wait for process to change state
SYNOPSIS
       #include 
       #include 
       pid_t wait(int *status);
       pid_t waitpid(pid_t pid, int *status, int options);
       int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
                       /* This is the glibc and POSIX interface; see
                          NOTES for information on the raw system call. */

使用示例

#include 
#include 
#include 
#include 
int main()
{
	pid_t pid;
	int status = 0;
	pid = fork();
	if(pid == -1){
		printf("fork failed\n");
		return 1;
	}else if(pid){
		printf("The father return value is %d\n",pid);
		wait(&status);
		printf("The father pid is %d\n",status);
		printf("The father pid is %d\n",getpid());
		printf("The father ppid is %d\n",getppid());
		//while(1);
	}else{
		printf("The child return value is %d\n",pid);
		printf("The child pid is %d\n",getpid());
		printf("The child ppid is %d\n",getppid());
		//while(1);
	}
	return 0;
}
The father return value is 12118
The child return value is 0
The child pid is 12118
The child ppid is 12117
The father pid is 0
The father pid is 12117
The father ppid is 10305

你可能感兴趣的:(Linux,C/C++,嵌入式)