Note1:APUE引言

一、UNIX/Linux前世今生

UNIX来源

20世纪60年代是大型、复杂操作系统盛行的年代,比如IBM的OS/360和Honeywell的Multics系统。OS/360是历史上最成功的软件项目之一,而 Multics虽然持续存在了多年,却从来没有被广泛应用过。贝尔实验室曾经是Multics项目的最初参与者,但是因为考虑到该项目的复杂性和缺乏进展而于1969年退出。鉴于Mutics项目不愉快的经历, Bell实验室的 Ken Thompson 开始利用一台闲置的 PDP-7计算机开发了一种多用户,多任务操作系统。很快,Dennis Richie 加入了这个项目,在他们共同努力下诞生了最早的UNIX。Richie 受一个更早的项目——MULTICS的启发,将此操作系统命名为 Unix。早期UNIX是用汇编语言编写的,但其第三个版本用一种崭新的编程语言C重新设计了。C是 Richie 设计出来并用于编写操作系统的程序语言。通过这次重新编 写,Unix得以移植到更为强大的 DEC PDP-11/45与11/70计算机上运行。后来发生的一切,正如他们所说,已经成为历史。 Unix从实验室走出来并成为了操作系统的主流,现在几乎每个主要的计算机厂商都有其自有版本的Unix。

POSIX来源

20世纪80年代中期,随着UNIX成长后来占领了市场,公司多了,懂得人也多了,就分家了。Unix厂商试图通过加入新的、往往不兼容的特性来使它们的程序与众不同,麻烦也就随之而来了。为了阻止这种趋势,IEEE(电气和电子工程师协会)开始努力标准化Unix的开发,后来由 Richard Stallman 命名为“POSIX(Portable Operating System Interface of UNIX)”。结果就得到 了一系列的标准,称作Posix标准。这套标准涵盖了很多方面,比如Unix系统调用的C语言接口、shell程序和工具、线程及网络编程。“UNIX”这个名字由于法律关系,谁也不能说自己的操作系统是“UNIX”而只能说是“UNIX兼容”系统了。所以现 在“UNIX”系统严格意义上说是不存在的,存在的只是一个遥远的传说。那么现在那些Solaris,AIX,IRIS,macOS都是什么呢?那些都是各公司在他们硬件平提上作的商业UNIX,这些系统都遵循POSIX标准。

GNU来源

GNU就是GNU's Not Unix的缩写, GNU 的创始人Stallman认为UNIX虽然不是最好的操作系统,但是至少不会太差,而他自信有能力把UNIX 不足的地方加以改进,使它成为一个优良的操作系统,就是名为GNU的一个同UNIX兼容的操作系统,并且开发这 个系统的目的就是为了让所有计算机用户都可以自由地获得这个系统。任何人都可以免费地获得这个系统的源代码,并且可以相互自由拷贝GNU 是由自由软件基金会 (Free Software Foundation,FSF)的董事长Richard M. Stallman (RMS)于1984年发起的,如今已经有十几年的历史了。

GNU 开始的策略就是先开发UNIX已经有的程序(因为计划中GNU将会是一个与UNIX兼容的操作系统,而UNIX下的标准使用界面已经非常完善了,所以先依照这个标准开发应用程序,将来GNU自己的系统核心一出来,就立即可以使用所有先前开发的 GNU 应用程序),因此会先有emacs,GCC等工具软件开发出来。其中GCC更是GNU计划自立更生的一个重要步骤(不需要依 靠商业软件来产生/编译整个GNU系统),如今这套程序开发工具已经很成熟了。下一步要做的就是开发GNU的核心--Hurd 了,只要Hurd一开发出来,GNU 就是一套能够自我开机,真正自给自足,完整的自由操作系统。

Hurd是基于Mach这个微内核(micro kernel)上的操作系统核心。以后会使用尤他大学的Mach4(一个更为方便和快速的微内核),由于Hurd基于Mach,所以只要Mach移植到什么机器上,Hurd也立刻就是这种硬件平台的操作系统,就这一点而言,它是一种很前卫的操作系统。但是,GNU的操作系统核心Hurd一直处于实验阶段,没有任何可用性,实质上也没能开发出完整的GNU操作系统,但是GNU奠定了Linux用户基础和开发环境。自由软件基金会目前有一套以Linux为核心的GNU系统计 划。这个计划就是自由软件基金会支持的 Debian Linux。 Debian Linux 是GNU软件与公共软件(Public Domain Software) 最彻底的结合,它是一套完全由GNU和公共软件配置起来的,而且具有商业操作系统水平的操作系统。

Linux来源

Linux起源于一个学生的简单需求。Linus Torvalds,Linux的作者与主要维护者,在其上大学时所买得起的唯一软件是Minix。Minix是他的老师为讲解操作系统原理这门课写一个类似Unix操作系统,它被广泛用来辅助教学的简单操作系统。Linus 对Minix 不是很满意,于是决定自己编写软件。他以学生时代熟悉的Unix作为原型, 在一台Intel 386 PC上开始了他的工作。他的进展很 快,受工作成绩的鼓舞,他将这项成果通过互连网与其他同学共享,主要用于学术领域。有人看到了这个软件并开始分发。每当 出现新问题时,有人会立刻找到解决办法并加入其中,很快的, Linux成为了一个操作系统。值得注意的是Linux并没有包括 Unix源码。它是按照公开的POSIX标准重新编写的。Linux大量使用了由麻省剑桥免费软件基金的GNU软件,同时Linux自身也 是用它们构造而成。

 

二、站在十万八千里的高度

在linux/unix的世界里,“万般皆下品,一切皆文件!”这句话是linux/unix的哲学核心思想。从1991.10.5年 Linus Torvalds 在自己学校FTP站点上正式向外发布第一个稳定的Linux内核工作版本到今天,正是由于这种“简单粗暴而又妖娆”的设计,才使得今天发生翻天覆地变化,我们在Linux/UNIX下编程时依然使用同一套API(Application Program Interface)。12年前的我刚开始接触Linux编程时学习的是大神 Richard Stevens 所著的《UNIX高级环境编程,业界简称APUE》和《UNIX网络编程,业界简称UNP》,12年后的今天,在带大家学习Linux下编程时依然倍加推崇这两本书。其中《APUE》是所有Linux下所有 程,序开发者的入门必备良药,《UNP》是所有从事Linux网络编程人员的必读书籍。

从现在开始,我们就开始带领大家走进Linux下的编程世界,而这个窗户就是《APUE》。在《APUE》这本书基本上覆盖了 Linux下所有编程相关的知识点,结合这么多年的嵌入式Linux开发经验,我把这本书需要重点掌握的内容大致分为以下几大块:

  • 文件I/O: open()、read()、write()、ioctl()、close()
  • 多进程编程: fork()、getpid()、getppid()、exec*()、system()、popen()
  • 多线程编程: pthread_create()、pthread_join()、pthread_exit()
  • 网络编程: socket()、bind()、connect()、accept()、read()/recv()、write()/send()、close()
  • 多路复用: select()、poll()、epoll()
  • 进程间通信(IPC): 管道(pipe)、命名管道(named pipe/FIFO)、消息队列(Message Queue)、信号量(Semophore )、信 号(signal)、共享内存(Shared Memory)、网络通信(sockt和named socket)

 

三、系统调用与库函数

Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions)。在《APUE》这本书中讲的绝大部分函数都是系统调用,而非库函数。

系统调用

系统调用,我们可以理解是操作系统为用户提供的一系列操作的接口(API),这些接口提供了对系统硬件设备功能的操作。可 以举个例子,我们最熟悉的 hello world 程序会在屏幕上打印出信息,程序中调用了printf() 函数,而库函数 printf 是将需要打印的信息输出到屏幕这个硬件设备上。我们知道,对于所有硬件设备的操作都需要驱动程序,而驱动程序是由操作系统内核实现的。这也就意味着我们的printf()函数最终需要调用Linux内核的相关函数来操作屏幕这个设备,而这些函数就是系统调用。事实上,printf()库函数的实现里最终会调用系统调用 write()

库函数

库函数可以理解为是对系统调用的一层封装。系统调用作为内核提供给用户程序的接口,它的执行效率是比较高效而精简的, 但有时我们需要对获取的信息进行更复杂的处理,或更人性化的需要,我们把这些处理过程封装成一个函数再提供给程序员,更方便于程序猿编码。譬如在接下来的学习过程中,我们会学习read(int fd, char *buf, int size)这个系统调用,这个函数是从某个文件(由fd)标志中,读取最多不超过size个字节的数据并存放到buf中去,在这个系统调用中我们只能指定读N个字节的数据,而对于想一次读取一行这样的需求则可以调用库函数fgets()来实现,这在《C Primer Plus》的文件/IO中讲到,当然在《C Primer Plus》里提到的所有函数都是库函数。

系统调用和库函数

库函数有可能包含有一个系统调用,有可能有好几个系统调用,对于不需要涉及内核的功能的库函数也不需要调用系统调用, 比如strcpy()、strstr()、strlen()这些函数等。 对于一个功能,我们有时既可以使用系统调用来实现,也可以使用库函数来实现,也没有强制的规定,根据大家的实际需求来选择。譬如对于文件的操作,我们可以使用open()、read()、write()、close()这些系统 调用实现,当然我们也可以使用fopen()、fread()、fwrite()、fgets()、fclose()这些库函数来实现,只有对比了解他们各自的特性我们针对不同的情况作出一个最优的选择。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值