热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Linux中exec系列函数的应用

这段时间在研究linux中用户登陆和shell执行程序的原理。我们知道,shell命令分为内部命令和外部命令,内部命令有诸如cd,history,exi

这段时间在研究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的进程树,如下:

  • [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

可以看到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)

把此文件保存为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一起把所有参数传递给这个函数。


推荐阅读
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 从批量eml文件中提取附件的Python代码实现方法
    本文介绍了使用Python代码从批量eml文件中提取附件的实现方法,包括获取eml附件信息、递归文件夹下所有文件、创建目的文件夹等步骤。通过该方法可以方便地提取eml文件中的附件,并保存到指定的文件夹中。 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文介绍了在RHEL 7中的系统日志管理和网络管理。系统日志管理包括rsyslog和systemd-journal两种日志服务,分别介绍了它们的特点、配置文件和日志查询方式。网络管理主要介绍了使用nmcli命令查看和配置网络接口的方法,包括查看网卡信息、添加、修改和删除配置文件等操作。 ... [详细]
  • Python脚本编写创建输出数据库并添加模型和场数据的方法
    本文介绍了使用Python脚本编写创建输出数据库并添加模型数据和场数据的方法。首先导入相应模块,然后创建输出数据库并添加材料属性、截面、部件实例、分析步和帧、节点和单元等对象。接着向输出数据库中添加场数据和历程数据,本例中只添加了节点位移。最后保存数据库文件并关闭文件。文章还提供了部分代码和Abaqus操作步骤。另外,作者还建立了关于Abaqus的学习交流群,欢迎加入并提问。 ... [详细]
  • ZABBIX 3.0 配置监控NGINX性能【OK】
    1.在agent端查看配置:nginx-V查看编辑时是否加入状态监控模块:--with-http_stub_status_module--with-http_gzip_stat ... [详细]
  • DockerDataCenter系列(四)-离线安装UCP和DTR,Go语言社区,Golang程序员人脉社 ... [详细]
  • systemd-nspawn可以创建最轻量级的容器(ns的意思就是namespace),本文的实验平台是Ubuntu16.04,x86_64机器。本文的目的是:在Ubuntu中用syst ... [详细]
  • 我创建了一个SSH密钥,当我以admin身份在GitBash中运行ssh-Tgit@gitlab.com时,我得到W ... [详细]
author-avatar
用户rsvowi2rvt
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有