linux/unix编程:启动新进程

这里介绍三种启动新进程的方法: system()库函数、exec()家族函数、fork()函数

1. 启动另外一个进程

可以通过库函数system完成,它会启动一个新的shell,并在新的shell里启动一个进程。效率比较低
#include <stdlib.h>
int system (const char * string);

示例如下:

qingsong@db2a:~/linuxc$ cat pstest.c

qingsong@db2a:~/linuxc$ cat pstest.c 
/*filename: pstest.c*/
#include <stdlib.h>
#include <stdio.h>

int main()
{
        system("ps -al");
		printf("ps command finished\n");
        return 0;
}

qingsong@db2a:~/linuxc$ gcc -o pstest pstest.c && ./pstest 
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 T  1000  2876 58189  0  80   0 -  1054 signal pts/0    00:00:00 1.9.1
0 S  1000 41102 58189  0  90  10 -  1053 wait   pts/0    00:00:00 pstest <--原进程,PID为41102
0 S  1000 41103 41102  0  90  10 -  1116 wait   pts/0    00:00:00 sh <--原进程调用system启动的shell, PPID为41102
0 R  1000 41104 41103  0  90  10 -  2502 -      pts/0    00:00:00 ps <--原进程调用system启动的shell里发起的命令,PPID为41103
ps command finished
qingsong@db2a:~/linuxc$ 


2. 替换进程

可以使用exec系列函数,一共6个,它们可以把当前进程替换为另一个进程,简介如下:

NAME
       execl, execlp, execle, execv, execvp, execvpe - execute a file

SYNOPSIS
       #include <unistd.h>

       extern char **environ;

       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, char *const argv[]);
       int execvp(const char *file, char *const argv[]);
       int execvpe(const char *file, char *const argv[],
                   char *const envp[]);
DESCRIPTION
       The  exec()  family  of  functions replaces the current process image with a new process image.  The functions
       described in this manual page are front-ends for execve(2).  (See the manual page for  execve(2)  for  further
       details about the replacement of the current process image.)

       The initial argument for these functions is the name of a file that is to be executed.

       The const char *arg and subsequent ellipses in the execl(), execlp(), and execle() functions can be thought of
       as arg0, arg1, ..., argn.  Together they describe a list of one or more pointers  to  null-terminated  strings
       that represent the argument list available to the executed program.  The first argument, by convention, should
       point to the filename associated with the file being executed.  The list of arguments must be terminated by  a
       NULL pointer, and, since these are variadic functions, this pointer must be cast (char *) NULL.

第一个参数是要执行的文件名,最后一个参数是空指针。可以看到,下面的程序中,第一个execl函数后面的两个printf和一个execl都没有执行,因为进程本身已经被替换掉了:

qingsong@db2a:~/linuxc$ cat exetest1.c 
/*filename: exetest.c*/
#include <unistd.h>
#include <stdio.h>

int main()
{
        execl("/bin/ps","ps","-al",(char*)0);
        printf("ps command finished\n");
        execl("/bin/date","date", (char*)0);
        printf("date command finished\n");

        return 0;
}
qingsong@db2a:~/linuxc$ gcc -o exetest1 exetest1.c 
qingsong@db2a:~/linuxc$ ./exetest1 
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 T  1000  2876 58189  0  80   0 -  1054 signal pts/0    00:00:00 1.9.1
0 R  1000 41467 58189  0  90  10 -  2502 -      pts/0    00:00:00 ps <--只有这一个进程,没有原来的exetest1进程
qingsong@db2a:~/linuxc$ 

3. Fork一个子进程

使用fork可以复制一个进程,新产生的进程是原来进程的子进程,需要用到fork函数,函数返回值为0的进程是子进程。示意图如下:‘


NAME
       fork - create a child process

SYNOPSIS
       #include <unistd.h>

       pid_t fork(void);

DESCRIPTION
       fork()  creates  a new process by duplicating the calling process.  The new process, referred to as the child,
       is an exact duplicate of the calling process, referred to as the parent, except for the following points:

       *  The child has its own unique process ID, and this PID does not match the ID of any existing  process  group
          (setpgid(2)).

       *  The child's parent process ID is the same as the parent's process ID.

       *  The child does not inherit its parent's memory locks (mlock(2), mlockall(2)).
	   ....

下面的程序,使用fork产生了子进程,父进程和子进程各自做不同的事情:

qingsong@db2a:~/linuxc$ cat forktest.c 
/* filename forktest.c */
#include <unistd.h>      
#include <stdlib.h>  
#include <stdio.h>

int main()
{
        pid_t pid;
        char * msg="This is a fork test program";

        pid=fork();

        if (pid < 0)
                printf("Fork error\n");
        else if (pid == 0)
        {
                sleep(5);
                printf("This is child begin\n");
                printf("%s\n",msg);
                printf("This is child end\n");
        }
        else 
        {
                printf("This is parent begin\n");
                printf("%s\n",msg);
                system("ps -al");
                printf("This is parent end\n");
        }

        return 0;
}
qingsong@db2a:~/linuxc$ gcc -o forktest forktest.c 
qingsong@db2a:~/linuxc$ ./forktest
This is parent begin
This is a fork test program
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 T  1000  2876 58189  0  80   0 -  1054 signal pts/0    00:00:00 1.9.1
0 S  1000 39703 58189  0  90  10 -  1054 wait   pts/0    00:00:00 forktest <<--最原始的进程
1 S  1000 39704 39703  0  90  10 -  1053 hrtime pts/0    00:00:00 forktest <<--由原进程fork出来的新进程
0 S  1000 39705 39703  0  90  10 -  1116 wait   pts/0    00:00:00 sh <<--由原进程调用system函数产生的shell
0 R  1000 39706 39705  0  90  10 -  2502 -      pts/0    00:00:00 ps <<--由原进程调用system函数产生的shell里执行的命令
This is parent end
qingsong@db2a:~/linuxc$ This is child begin
This is a fork test program
This is child end

qingsong@db2a:~/linuxc$ 

1. 子进程是由父进程复制过来的,所以,都能打印出消息msg
2. ps -al的输出中,有两个forktest,其中PID为的 39704 是子进程,可以看到它的PPID为 39703
3. 子进程要比父进程慢5秒,如果在父进程结束后的5s之内,在另外一个shell里查看ps -al的输出,如下,能够看到由于父进程已经结束,子进程的父进程变为1.

qingsong@db2a:~$ ps -al
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 T  1000  2876 58189  0  80   0 -  1054 signal pts/0    00:00:00 1.9.1
1 S  1000 39704     1  0  90  10 -  1053 hrtime pts/0    00:00:00 forktest
0 R  1000 39712 39666  0  80   0 -  2502 -      pts/2    00:00:00 ps


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值