月下博客

程序的运行流程

科普性文章,希望对想学习linux系统的人有帮助。如有错误或不当之处,欢迎指正。

计算机程序可以分为两种:GUI(Graphical User Interface)CLI(Command Line Interface) 两种。GUI程序有图形界面,能过响应鼠标,键盘,外设等发送的消息,对用户友好;CLI程序以命令行方式运行在终端下,具有效率高的特点,但是掌握起来困难大。windows和mac系统上的程序大部分都是GUI程序,适用于大部分的用户使用。linux图形桌面发行版的程序当然也是GUI程序,不过linux的桌面市场份额很小,基本上用在服务器领域,所以学习linux主要用的是CLI程序。(安卓是基于linux的,上面的程序主要也是GUI程序)

一个程序的运行过程是怎么样的呢?这个过程是这样的:

找到程序的可执行文件->配置运行环境->执行程序代码

从上可以看出,逻辑还是非常简单明了的。但是这其中有一些细节,却值得一说。

第一步:找到程序的可执行文件

在windows上,这个问题不大,基本上都是通过点击鼠标就完成了。而在linux上,却经常有敲某个命令的时候出现“command not found”的提示,这是为什么?因为系统没有找到命令的可执行文件在哪里。

那为什么windows用户很少遇到这种情形?windows上的程序,主要是通过点击图标来启动,而大部分图标都是快捷方式,其内容包含了真正渴执行文件的绝对位置和启动参数,所以很少有这个问题。如果在cmd或者powershell下打开程序,和Linux上的情况大致相同。


target指定了程序的位置和启动参数

怎样让操作系统找到我们的命令所在位置?第一个答案非常简单:使用绝对路径指明程序的位置。例如有个demo的可执行文件,可以使用 /home/tlanyan/demo args来运行。这个命令里,程序的位置已经明确指出,所以能够正常运行。

另外一种常用的做法是更改系统的PATH环境变量。顾名思义,PATH就是路径的意思。不管哪个系统,PATH都是一个非常重要的系统变量(windows上写做Path之类)。这个变量告诉系统从哪些路径下去寻找当前用户可用的可执行程序。linux下可以使用 echo $PATH 查看其值,一个典型的输出是:

/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/tlanyan/bin

常用的 ls 命令,位于 /bin 目录下,所以命令 ls 可以认为执行了 /bin/ls

所以敲击一个命令提示没有找到的时候,有两种可能:1. 这个命令不在PATH变量指示的文件夹下; 2. 在PATH指示的文件夹里,但是没有执行权限。对于第一种情形,解决方法之一是上面提到的使用绝对路径来启动程序。一劳永逸的方法则是程序所在文件夹添加到PATH变量题。

在终端下可以使用 export PATH=$PATH:/new/path 来临时更新PATH变量。如果希望更改一直有效,需要写到诸如 /etc/bashrc, ~/.bashrc, ~/.bash_profile等文件里。注意两点:

  1. 直接写到文件里不会更新当前会话的PATH变量,需要使用source命令来更新,或者关闭终端重新连接;
  2. PATH里的文件是一次查找的,所以有顺序。系统找命令的时候,如果在某个文件夹下找到了对应命令就会停止寻找,所以如果有相同的命令的话,请选择将新路径放在前面还是后面来区分其优先级。

关于执行权限问题,linux下的文件使用 ‘x’ 指示符来指明文件是否可执行文件,而非windows上的使用exe拓展名。所以要执行某个文件,请确认对其具有可执行的权限。如果文件的属主是别人,则需要其他人来授权;如果文件属主是自己,则可以使用 chmod u+x 来为文件增加可执行权限。这种情况多用于自己编写的脚本文件。

第二步:配置程序运行环境

对于使用CLI程序的用户,这一步可以直接忽略,因为影响比较小。

如果深究,操作系统在运行程序前还是做了一些工作的。比较重要的是初始化了这些环境:程序的工作目录;标准输入输出通道。程序控制块等信息对操作系统有用,但是对用户来说影响甚微。

程序的工作目录对程序运行而言也是非常重要的。例如在程序中打开一个文件,如果使用的是相对路径,那么其基地址就是工作目录。在windows上,是快捷方式中“Start in”指定的目录。

标准输入输出通道对程序的数据流产生影响,对于CLI程序而言,标准输入输出通道不会改变:从终端获取和打印数据。

第三步:执行程序代码

准备工作准备完毕之后,接下来就是按照程序的代码来运行。剩下来除了程序运行,似乎就没什么事了。但是实际使用中并非总是如此,经常会碰到 ‘error while loading shared libraries:xxx.so’ 的提示。这又是为何?

程序在生成的时候如果使用了动态链接库的方式,那么引用的代码会位于外部的库文件而非包含在执行程序中。由于安装的时候一般只有可执行文件,那么如果库文件没有或者程序找不到,就会出现上述提示。

对于未安装引用库的情绪,需要安装该库文件才能支持程序的运行。如果安装了,但是程序提示上述错误,那么则是程序调用的时候没有找到该动态链接库。

和PATH变量类似,系统使用LD_LIBRARY_PATH这个环境变量来指定动态链接库的位置。如果有所需要的动态链接库文件,只需要更新这个变量,然后系统即可找到。更新LD_LIBRARY_PATH的同样使用export: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/new/path

总结

本文通过介绍程序运行流程介绍了影响程序运行的两个最重要的环境变量:PATH和LD_LIBRARY_PATH。对于初学者,弄清楚了这两个变量则在使用过程中能减少许多问题。