在编程过程中经常需要启动一个新进程,有时需要从当前进程中启动其它程序来并行或替换当前进程(即切换至其它程序),这里作一个小结,记录一下常用的几种方式,作为笔记,以便日后方便查找,高手们请飘过~
一、通过system()函数来启动新程序。
即通过系统调用函数,int system(char *string)来启动,它等同在shell中执行该命令,不足之处是它依赖shell,(底层是通过/bin/sh命令来执行该程序的)。
二、通过替换当前进程映像,切换至新程序。
常用的函数是exec组函数,函数原型有:
int execl(const char *path,const char *arg0,...,(char *)0);
int execlp(const char *file,const char *arg0,...,(char *)0);
int execle(const char *path,const char *arg0,...(char *)0,char *const envp[])
int execv(const char *path,char *const argv[]);
int execvp(const char *file,char *const argv[]);
int execve(const char *path,char *const argv[],char *const envp[]);
三、通过复制当前进程映像,启动新进程。
常用的函数是fork()函数,原型是pid_t fork(void ),此种方式创建新进程后,与原进程几乎一模一样,但有自己独立的数据空间,执行代码也一致,是一种被广泛使用的方式。
上述是简略说明三种方式,可参考下面图来详细区别,据自己的需要选择合适的方式。
下面是我的练习
代码文件:system.c
1 #include <unistd.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4
5 /***********************************************************
6 功能说明:通过system()方法启动新进程
7 author: linux.sir@qq.com
8
9 ***********************************************************/
10 int main(int argc, char * argv[])
11 {
12
13 char *sh = "df";
14
15 int r = system(sh);
16 if(r<0)
17 {
18 printf("system error for %m\n", r);
19
20 }
21
22 }
运行结果:
代码文件:exec.c
1 #include <unistd.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <errno.h>
5 /***********************************************************
6 功能说明:exec函数组的使用
7 author: linux.sir@qq.com
8
9 ***********************************************************/
10
11 void newExeclp();
12 void newExecl();
13 void newExecve();
14
15
16 int main(int argc, char * argv[])
17 {
18 //newExeclp();
19 //newExecl();
20 newExecve();
21
22 }
23 /**********************************************************
24
25 方法功能:通过execlp()执行命令:ps -ef
26
27 **********************************************************/
28 void newExeclp()
29 {
30
31 char *sh = "ps";
32 char *arg0 = "ef";
33 printf("current PID=%d from newExeclp()\n", getpid());
34
35 int r = execlp(sh, arg0, (char *)0); //切换成新的进程,原进程不再执行。
36 if(r<0)
37 {
38 printf("execlp error for %m\n", errno);
39
40 }
41
42 printf("current PID=%d\n", getpid());
43
44
45 }
46
47 /**********************************************************
48
49 方法功能:通过execl()函数执行自定义的命令system
50
51 **********************************************************/
52 void newExecl()
53 {
54 char *path = "/home/magc/workspace/0126/system";
55 printf("current PID=%d from newExecl()\n", getpid());
56 execl(path,"",(char *)0);
57 printf("execl end\n" );
58
59 }
60
61 /**********************************************************
62
63 方法功能:通过execve()函数来执行自定义的命令system
64
65 **********************************************************/
66
67 void newExecve()
68 {
69
70 const char * file = "system";
71
72 char *const argv[] =
73 {
74 ""
75 };
76
77
78
79 char *const env[] =
80 {
81 "PATH=/home/magc/workspace/0126:/bin"
82 };
83
84 printf("current PID=%d from newExecve()\n", getpid());
85 int r = execve(file, argv, env);
86 if(r<0)
87 {
88 printf("execve error for %m\n",errno );
89 }
90
91 //execve(const char *FILENAME, char *const ARGV[], char *const ENV[])
92
93 printf("execve end\n" );
94 }
运行结果:
注:这里只演示了newExecve()方法的结果,因为在main函数里只能调用其中一个(切换到新进程后,原来的代码将不再执行了),不方便演示所有函数。
代码文件:process_fork.c
1 #include <assert.h>
2 #include <ctype.h>
3 #include <errno.h>
4 #include <limits.h>
5 #include <string.h>
6 #include <stdarg.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <unistd.h>
10 /***********************************************************
11 功能说明:进程控制相关编程知识--fork()
12 author: linux.sir@qq.com
13
14 ***********************************************************/
15
16 void newFork();
17
18
19
20 int main(int argc, char * argv[])
21 {
22 //getID();
23 newFork();
24 //newVfork();
25
26 //return 0;
27 //exit(2);
28 //_exit(2);
29
30
31 }
32
33 /**********************************************************
34
35 方法功能:创建新进程,fork()
36 注:fork()是通过复制当前进程得到一个独立的新进程,新进程与原进程几乎一模一样的,
37 不过有自己的数据空间、环境和文件描述符,执行的代码也相同(相同代码但是复制而来,独立的),
38 都有自己的数据段(也是复制而来的)
39
40 **********************************************************/
41 void newFork()
42 {
43 printf("current pid = %d\n", getpid());
44
45 int count = 0;
46
47
48 pid_t pid =fork();
49
50 // 此时已经有两个进程同时在执行下面的代码了。
51
52 // printf("after fork ,pid=%d", pid);
53
54 count++;
55
56 if(pid<0)
57 {
58 printf("fork error for %m\n", errno);
59
60 }else if(pid ==0)
61 {
62 count++;
63
64 printf("this is child ,pid is %d,ppid is %d\n", getpid(),getppid());
65
66 }else
67 {
68 count++;
69
70 printf("this is parent,pid is %d\n", getpid());
71
72 }
73
74 printf("count = %d\n", count);
75 }
运行结果:
注:新进程的数据空间是独立的,所以count都是自己独立的,均为2.
代码文件:process_vfork.c
1 #include <assert.h>
2 #include <ctype.h>
3 #include <errno.h>
4 #include <limits.h>
5 #include <string.h>
6 #include <stdarg.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <unistd.h>
10 /***********************************************************
11 功能说明:进程控制相关编程知识--vfork()
12 author: linux.sir@qq.com
13
14 ***********************************************************/
15
16
17 void newVfork();
18
19
20 int main(int argc, char * argv[])
21 {
22
23
24 newVfork();
25
26
27 }
28
29
30 /**********************************************************
31
32 方法功能:创建新进程vfork()
33
34 **********************************************************/
35
36 void newVfork()
37 {
38 int count = 1;
39
40 printf("current pid = %d\n", getpid());
41
42 pid_t pid = vfork();
43
44 // count++;
45
46 if(pid<0)
47 {
48 printf("vfork error for %m\n", pid);
49
50 }else if(pid==0)
51 {
52
53 count++;
54
55 printf("this is child ,pid=%d\n", getpid());
56 printf("count = %d\n",count);
57 _exit(0); //使子进程结束,然后父进程才能被调度执行。
58
59 }else
60 {
61 count++;
62
63 printf("this is parent , pid=%d\n", getpid());
64 printf("count = %d\n",count);
65 }
66 }
运行结果:
注:这里得到的结果是与上面process_fork的结果相同,而不是像其它地方说的,count一个值为2,后面一个值为3,有待考究。若有高手明白,请指教。