众所周知,Linux系列知识极其重要,公司面试、实际开发都需要用到。最近看了一些资料之后,发觉自己很多地方没有掌握到位,于是开始逐一查阅,顺便整理了这个懒人版供大家参考。
每个需要详细了解问题下面需要的信息都给出了相应的参考链接,有些还配上了实际操作,相信你认真看完本文之后对于UNIX操作系统基础能有一个更加清晰的认识。
Linux,Mac OS X,BSD系列与 Solaris
shell是一个命令语言解释器,是用户和UNIX内核直接的接口,它拥有自己内建的shell命令集,shell也能被系统中其他应用程序所调用。用户在提示符下输入的命令都由shell先解释然后传给UNIX核心。
Unix常用命令: http://kimi.it/23.html
ls 列出目录下的文件
内部命令在系统启动时就调入内存,是常驻内存的,所以执行效率高。
外部命令是系统的软件功能,用户需要时才从硬盘中读入内存。
内部命令:内部命令被构建在shell之中。当执行shell命令时,内部命令的执行速度非常快。这是因为没有其他的进程因为执行这条命令而被创建。比如说,当我们执行“cd”命令时,没有进程被创建。在执行过程中只是简单的改变当前的目录。
外部命令:外部命令并没有被构建在shell中。这些可执行的外部命令保存在一个独立的文件当中。当一个外部命令被执行时,一个新的进程即被创建同时命令被执行。比如说,当我们执行“cat”(通常被保存在/usr/bin目录下)命令时,然后/usr/bin/cat被执行。
头文件作为一种包含功能函数、数据接口声明的载体文件,主要用于保存程序的声明。
C语言的标准头文件:ISOC标准定义的头文件
操作系统提供的头文件:POSIX标准定义的头文件
-o 制定目标名称,缺省的时候,gcc 编译出来的文件是a.out
-e 使用-E 选项,执行预处理工作
-static 此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么动态连接库,就可以运行
-Wall 生成所有警告信息
静态库是在链接阶段被链接的,所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行。
有别于静态库,动态库的链接是在程序执行的时候被链接的。所以,即使程序编译完,库仍须保留在系统上,以供程序运行时调用。
gcc -static
文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。
Unix可以把一个能随机存取的存储介质(如:硬盘、软盘和光盘)上的存储空间划分成一致多个区域,每个区域都可以像独立的物理设备一样单独进行管理和数 据存取,这样的存储区域,即是逻辑设备。在逻辑设备上按照一定的格式进行划分,就构成了逻辑文件系统,简称文件系统。
在linux中的每一个文件或目录都包含有访问权限,这些访问权限决定了谁能访问和如何访问这些文件和目录
chmod [mode] 文件名(其中mode可用二进制数表示)
u :目录或者文件的当前的用户
g :目录或者文件的当前的群组
o :除了目录或者文件的当前用户或群组之外的用户或者群组
(u) (g) (o)
— = 0
rwx = 7
0777–>-rwx rwx rwx
对所有用户开放所有权限
$ ls -l sobsrc. tgz
-rw-r–r– 1 root root 483997 Ju1 l5 17:3l sobsrc. tgz
r代表只读,w代表写,x代表可执行,-代表空许可。
注意这里共有10个位置。第一个字符指定了文件类型。在通常意义上,一个目录也是一个文件。如果第一个字符是横线,表示是一个非目录的文件。如果是d,表示是一个目录。
管道:UNIX操作系统进程间通信的一种方式,一个进程的输出直接传递到另一个进程作为输入
二者都用来复制打开的文件描述符,复制成功后和复制源共享同一个文件表。
int dup (int filedes);
int dup2 (int filedes, int filedes2);
图解
理解具体情况,需要了解由内核维护的3个数据结构:
进程级文件描述符表(file descriptor table)
系统级打开文件表(open file table)
文件系统i-node表(i-node table)
这3个数据结构之间的关系如下图所示:
内核使用三种数据结构表示打开的文件,分别是文件描述符表、文件表和 V 节点表。
(1) 每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述符表,每个描述符占用一项。与每个文件描述符相关联的是:
(a) 文件描述符标志。
(b) 指向一个文件表项的指针。
(2) 内核为所有打开文件维持一张文件表。每个文件表项包含:
(a) 文件状态标志(读、写、添写、同步和非阻塞等)。
(b) 当前文件偏移量。
(c) 指向该文件 V 节点表项的指针。
(3) 每个打开文件(或设备)都有一个 v 节点(v-node)结构。v 节点包含了文件类型和对此文件进行各种操作的函数的指针。v 节点还包含了从磁盘读取的 i 节点(i-node)的信息,i 节点信息包含了文件的所有者、文件长度、文件所在的设备、指向文件的实际数据块在磁盘上的所在位置的指针等。
进程组是一个或多个进程的集合,通常它们与一组作业相关联,可以接受来自同一终端的各种信号。每个进程组都有唯一的进程组ID(整数,也可以存放在pid_t类型中)。
会话是一个或多个进程组的集合。
每个进程组都有一个组长进程,组长进程的标识是进程组ID等于其进程ID。进程调用setsid函数创建一个新的会话,该进程会变成新会话的会话首进程,该进程也成为一个新进程组的组长进程。如果此调用进程已经是一个进程组的组长,则此函数返回出错。
调用getsid函数返回调用进程的回话首进程的进程组id。
由fork创建的新进程被称为子进程(child process)。该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是新进程(子进程)的进程 id。将子进程id返回给父进程的理由是:因为一个进程的子进程可以多于一个,没有一个函数使一个进程可以获得其所有子进程的进程id。对子进程来说,之所以fork返回0给它,是因为它随时可以调用getpid()来获取自己的pid;也可以调用getppid()来获取父进程的id。(进程id 0总是由交换进程使用,所以一个子进程的进程id不可能为0 )。
fork之后,操作系统会复制一个与父进程完全相同的子进程,虽说是父子关系,但是在操作系统看来,他们更像兄弟关系,这2个进程共享代码空间,但是数据空间是互相独立的,子进程数据空间中的内容是父进程的完整拷贝,指令指针也完全相同,子进程拥有父进程当前运行到的位置(两进程的程序计数器pc值相同,也就是说,子进程是从fork返回处开始执行的),但有一点不同,如果fork成功,子进程中fork的返回值是0,父进程中fork的返回值是子进程的进程号,如果fork不成功,父进程会返回错误。可以这样想象,2个进程一直同时运行,而且步调一致,在fork之后,他们分别作不同的工作,也就是分岔了。这也是fork为什么叫fork的原因
至于那一个最先运行,可能与操作系统调度算法有关,而且这个问题在实际应用中并不重要,如果需要父子进程协同,可以通过原语的办法解决。
父子进程共享文件描述符的条件:在fork之前打开文件。
父子进程关系:fork出的子进程和父进程- 晴天的专栏- 博客频道- CSDN.NET
未完待续
欢迎大家在评论区批评指正与交流,本博客将长期更新维护
* 简书博客: http://www.jianshu.com/u/fc5814d052af
* CSDN: http://blog.csdn.net/agodj
* Github :https://github.com/LJ147
* 个人主页 : http://www.caozhenzhen.com
* 邮箱:[email protected]
* 本文链接:http://www.jianshu.com/p/a2dc2907ec28
* 下集预告:http://www.jianshu.com/p/61814320e8be