Linux系统编程_9_进程控制之exec 函数

exec函数

当进程调用exec函数时,该进程的执行程序完全的替换为新程序。新程序从它的main函数开始执行;

使用fork函数创建一个子进程后,子进程往往会使用exec函数去执行另一个程序。

注意:调用exec函数并不会创建新进程,所以创建前后的进程ID不会改变,exec只是用一个全新的程序替换了当前正在运行的程序的代码段、数据段、堆、栈。

#include <unistd.h>

extern char **environ;

int execl(const char *path, const char *arg, ...);

int execv(const char *path, char *const argv[]);

int execle(const char *path, const char *arg, ..., char * const envp[]);

int execve(const char *path, char *const argv[], char *const envp[]);

int execlp(const char *filename, const char *arg, ...);

int execvp(const char *filename, char *const argv[]);

这么多函数如何记忆?

带有字母p的,代表第一个参数是filename,并根据PATH环境变量搜索可执行文件;

带有字母l的,代表函数取一个参数表;(与字母v互斥;希望接收以逗号分隔的参数列表,列表以NULL指针作为结束标志)

带有字母v的,代表函数取一个argv[]; (希望接收到一个以NULL结尾的字符串数组的指针)

带有字母e的,代表函数取一个envp[]数组;(函数传递指定参数envp,允许改变子进程的环境,无后缀e时,子进程使用当前程序的环境)

下面是例子:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    pid_t pid;
    int status;
    char *arg[] = {"ps" "-l", NULL};

    // execl
    pid = fork();
    if(-1 == pid)
    {
        printf("Fork error!\n");
        return -1;
    }
    else if(0 == pid)
    {
        if(-1 == execl("/bin/ls", "ls", "-a", NULL))
        {
            perror("execl error!");
            exit(-1);
        }
    }
    waitpid(pid, &status, 0);

    // execv
    if(0 == (pid=fork()))
    {
        if(-1 == execv("/bin/ps", arg))
        {
            perror("execv error!");
            exit(-1);
        }
    }
    waitpid(pid, &status, 0);

    // execle
    if(0 == (pid=fork()))
    {
        if(-1 == execle("/bin/ps", "ps", "-l", NULL, NULL))
        {
            perror("execle error!");
            exit(-1);
        }
    }
    waitpid(pid, &status, 0);

    // execve
    if(0 == (pid=fork()))
    {
        if(-1 == execve("/bin/ps", arg, NULL))
        {
            perror("execve error!");
            exit(-1);
        }
    }
    waitpid(pid, &status, 0);

    // execlp
    if(0 == (pid=fork()))
    {
        if(-1 == execlp("ps", "ps", "-l", NULL))
        {
            perror("execle error!");
            exit(-1);
        }
    }
    waitpid(pid, &status, 0);

    return 0;
}

运行结果:

.  ..  echo.sh  main

PID TTY          TIME CMD

11120 pts/1    00:00:01 bash

20964 pts/1    00:00:00 main

20966 pts/1    00:00:00 ps

F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD

0 S   506 11120 11119  0  80   0 -  1745 -      pts/1    00:00:01 bash

0 S   506 20964 11120  0  80   0 -   459 -      pts/1    00:00:00 main

0 R   506 20967 20964  0  80   0 -   694 -      pts/1    00:00:00 ps

PID TTY          TIME CMD

11120 pts/1    00:00:01 bash

20964 pts/1    00:00:00 main

20968 pts/1    00:00:00 ps

F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD

0 S   506 11120 11119  0  80   0 -  1745 -      pts/1    00:00:01 bash

0 S   506 20964 11120  0  80   0 -   459 -      pts/1    00:00:00 main

0 R   506 20969 20964  3  80   0 -  1618 -      pts/1    00:00:00 ps

时间: 2024-10-06 09:58:24

Linux系统编程_9_进程控制之exec 函数的相关文章

Linux系统编程_8_进程控制之fork_wait_waitpid函数

fork函数: #include <unistd.h> pid_t fork(void); fork用来创建一个子进程: 特点: fork调用后会返回两次,子进程返回0,父进程返回子进程的进程ID:fork返回后,子进程和父进程都从fork函数的下一条语句開始运行: 注意: fork之后,操作系统会复制一个与父进程全然同样的子进程,虽说是父子关系.可是在操作系统看来,他们更像兄弟关系,这两个进程共享代码空间,可是数据空间是互相独立的,子进程数据空间中的内容是父进程的完整拷贝.指令指针也全然同样

Linux系统编程之进程

前一段时间对文件I/O的基本操作基本操作做了总结,今天这里继续按照我的理解对linux系统编程的进程操作进行总结. 首先我们先理解几个概念:程序.进程.线程. 所谓程序,就是计算机指令的集合,它以文件的形式存储在磁盘上,进程是一个程序在其自身的地址空间中的一次执行活动.而线程进程内的一个执行单元,也是进程内的可调度实体.说完这个不知道大家理解了吗?反正我第一次听到这个概念以后看到的时候可以明白过后就忘记了,现在我给大家举一个例子帮助大家理解,大家都看电视剧吧,所谓程序,就是一个剧本,像什么<西游

嵌入式 Linux系统编程(五)——目录文件函数

嵌入式 Linux系统编程(五)--目录文件函数 Linux中目录也是文件,目录操作函数为标准IO库函数.主要函数如下: #include <sys/types.h> #include <dirent.h> DIR *opendir(const char *name); DIR *fdopendir(int fd); 成功返回一个指向目录流的指针,失败返回NULL,并且设置errno全局变量. #include <dirent.h> struct dirent *rea

Linux系统编程——Daemon进程

目录 Daemon进程介绍 前提知识 Daemon进程的编程规则 Daemon进程介绍 Daemon运行在后台也称作"后台服务进程". 它是没有控制终端与之相连的进程.它独立与控制终端.会话周期的执行某种任务. 那么为什么守护进程要脱离终端后台运行呢? 守护进程脱离终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的任何终端信息所打断. 那么为什么要引入守护进程呢? 由于在linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程

linux c编程:进程控制(四)进程调度

当系统中有多个进程到时候,哪个进程先执行,哪个进程后执行是由进程的优先级决定的.进程的优先级是由nice值决定的.nice值越小,优先级越高.可以看做越友好那么调度优先级越低.进程可以通过nice函数获取更改它的nice值,进程只能影响自己的nice值,不能影响其他进程的nice值 #include <unistd.h> int nice(int incr) incr参数被增加到调用进程的nice值上,如果nice值太大,系统直接将它降到最大合法值. 可以通过nice命令来查看系统的默认nic

Linux系统编程——特殊进程之僵尸进程

僵尸进程(Zombie Process) 进程已执行结束,但进程的占用的资源未被回收.这种进程称为僵尸进程. 在每一个进程退出的时候,内核释放该进程全部的资源.包含打开的文件.占用的内存等. 可是仍然为其保留一定的信息,这些信息主要主要指进程控制块的信息(包含进程号.退出状态.执行时间等).直到父进程通过 wait() 或 waitpid() 来获取其状态并释放(详细使用方法,请看<等待进程结束>). 这样就会导致一个问题,假设进程不调用wait() 或 waitpid() 的话, 那么保留的

Linux系统编程——特殊进程之守护进程

什么是守护进程? 守护进程(Daemon Process),也就是通常说的 Daemon 进程(精灵进程),是 Linux 中的后台服务进程.它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件. 守护进程是个特殊的孤儿进程,这种进程脱离终端,为什么要脱离终端呢?之所以脱离于终端是为了避免进程被任何终端所产生的信息所打断,其在执行过程中的信息也不在任何终端上显示.由于在 Linux 中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都

LINUX环境编程之进程控制(上)

一.进程标识 每个进程都有一个非负整型表示的唯一进程ID.虽然该id是唯一的,但是进程ID是可复用的.当一个进程终止后,其进程id就成为复用的候选者. 系统中有一些专用进程,但是具体细节随实现而不同.ID为0的进程通常是调度进程,常常被称为交换进程.该进程是内核的一部分,它并不执行任何磁盘上的程序,因此也被成为系统进程.进程ID 1通常是init进程,在自举过程结束时有内核调用.init进程绝不会终止,他是一个普通用户的用户进程(与交换进程不同,他不是内核中的系统进程),但是它以超级用户权限运行

linux系统编程之进程(七):system()函数使用【转】

本文转载自:http://www.cnblogs.com/mickole/p/3187974.html 一,system()理解 功能:system()函数调用“/bin/sh -c command”执行特定的命令,阻塞当前进程直到command命令执行完毕 原型: int system(const char *command); 返回值: 如果无法启动shell运行命令,system将返回127:出现不能执行system调用的其他错误时返回-1.如果system能够顺利执行,返回那个命令的退出