Linux中exec系列函数的应用
2014-09-05 17:27
267 查看
这段时间在研究linux中用户登陆和shell执行程序的原理。我们知道,shell命令分为内部命令和外部命令,内部命令有诸如cd,history,exit,echo等,常见的外部命令有ls,ping,netstat等,通过type命令可以查看一个命令是内部命令还是外部命令。当执行的命令是一个内部命令是,shell直接执行;那么shell是如何执行一个外部命令的呢?
Shell本身也是一个程序,程序之间调用的方式也有很多,例如popen,但shell成功的执行一个外部命令,要满足以下条件:
1,首先是shell能调用这个程序,这个是必须的前提。
2,第二是shell必须要等待外部程序执行完毕才能返回。
3,第三是外部程序执行时,shell必须要把所有的执行权限交给外部命令,且外部命令需要继承shell的状态,如当前工作目录,控制终端,根目录等等。
实际上在linux中,shell执行外部命令都是以子进程的方式执行,在通过pstree看到linux的进程树,如下:
[/code]
可以看到pstree属于bash的子进程。那么,shell执行外部命令的原理是什么呢?
当shell执行一个外部命令是,第一步是fork出一个子进程,shell获取传递进来的参数,然后子进程调用一种exec函数执行另一个程序,子进程执行的程序完全替换为新程序,因为exec不创建新的进程,所以前后的进程ID不会改变。下面代码可以用来模拟shell执行外部程序:
[/code]
把此文件保存为ba,增加执行权限,然后运行./ba ping www.hitoy.org,程序执行正常,运行pstree,发现有python产生一个ping的子程序。
Linux上,一个程序调用另外程序经常会采用这种先fork然后exec的方式。再来看一下exec,exec是linux上的一组函数,一共有6个,如下:
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 execve(const char *path, char *const argv[], char *const envp[]);
需要注意的是,上面的函数中,第一个参数path必须为路径名,filename可以是路径名也可以是文件名,当为文件名时,系统会在PATH环境变量中查找这个文件。另外一点需要注意的是,传递的arg值,必须从第0个参数开始都传递,也就是必须连同cmdline一起把所有参数传递给这个函数。
Shell本身也是一个程序,程序之间调用的方式也有很多,例如popen,但shell成功的执行一个外部命令,要满足以下条件:
1,首先是shell能调用这个程序,这个是必须的前提。
2,第二是shell必须要等待外部程序执行完毕才能返回。
3,第三是外部程序执行时,shell必须要把所有的执行权限交给外部命令,且外部命令需要继承shell的状态,如当前工作目录,控制终端,根目录等等。
实际上在linux中,shell执行外部命令都是以子进程的方式执行,在通过pstree看到linux的进程树,如下:
[root@home ~]# pstree
systemd-+-2*[agetty]
|-avahi-daemon---avahi-daemon
|-avahi-dnsconfd
|-crond
|-dbus-daemon
|-haveged
|-ifplugd
|-master---pickup
|-python
|-rngd
|-sshd-+-3*[sshd]
| `-sshd---bash---pstree
|-systemd---(sd-pam)
|-systemd-journal
|-systemd-logind
|-systemd-udevd
`-wpa_supplicant
[/code]
可以看到pstree属于bash的子进程。那么,shell执行外部命令的原理是什么呢?
当shell执行一个外部命令是,第一步是fork出一个子进程,shell获取传递进来的参数,然后子进程调用一种exec函数执行另一个程序,子进程执行的程序完全替换为新程序,因为exec不创建新的进程,所以前后的进程ID不会改变。下面代码可以用来模拟shell执行外部程序:
#!/usr/bin/env python
import os,sys
if sys.argv[1:]:
pid=os.fork()
else:
sys.exit(0)
if not pid:
filename=sys.argv[1]
argv1=filename
argvs=",".join(sys.argv[2:])
os.execlp(filename,argv1,argvs)
os.waitpid(pid,0)
[/code]
把此文件保存为ba,增加执行权限,然后运行./ba ping www.hitoy.org,程序执行正常,运行pstree,发现有python产生一个ping的子程序。
Linux上,一个程序调用另外程序经常会采用这种先fork然后exec的方式。再来看一下exec,exec是linux上的一组函数,一共有6个,如下:
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 execve(const char *path, char *const argv[], char *const envp[]);
需要注意的是,上面的函数中,第一个参数path必须为路径名,filename可以是路径名也可以是文件名,当为文件名时,系统会在PATH环境变量中查找这个文件。另外一点需要注意的是,传递的arg值,必须从第0个参数开始都传递,也就是必须连同cmdline一起把所有参数传递给这个函数。
相关文章推荐
- linux进程编程-替换进程映-exec系列函数(execl,execlp,execle,execv,execvp)使用
- linux的子进程调用exec( )系列函数
- Linux中exec()执行文件系列函数的使用说明
- Linux中backtrace()系列函数的应用实例
- linux的子进程调用exec( )系列函数
- linux系统编程之进程(五):exec系列函数(execl,execlp,execle,execv,execvp)使用
- linux进程编程-替换进程映-exec系列函数(execl,execlp,execle,execv,execvp)使用
- linux进程编程,exec系列函数(execl,execlp,execle,execv,execvp)使用
- 理解linux的exec系列函数
- Linux系统下的 exec系列函数
- linux系统编程之进程(五):exec系列函数(execl,execlp,execle,execv,execvp)使用
- linux系统编程之进程(三):exec系列函数
- 【经典转载】Linux进程学习系列之六 进程控制函数之exec()函数的学习
- Linux 多线程应用中如何编写安全的信号处理函数
- php的exec()函数执行外部Linux脚本问题
- Linux系列-Red Hat5平台下的Iptables防火墙应用(二)
- 嵌入式linux网络编程之connect()函数的高级应用
- PHP中exec、system等函数调用linux命令问题
- linux进程控制-exec系列
- Linux 多线程应用中如何编写安全的信号处理函数