Linux内核project导论——linux学习和职业曲线(刚開始学习的人,中级,高级都可參考)

Linux世界介绍

给自己定级

门外汉:
不会安装操作系统
不会用虚拟机(安装和使用)
入门级:
熟悉常见的发行版,甚至装过而且能用一些特殊发行版(比如kali)做过一些简单的图形界面的使用。
会一些最基础的命令(比如cd、ps、top、ls、ifconfig等这个级别的)
基础级:
能够使用一些常见的命令(touch、tail、date、find、du、fdisk、less、pidof等这个级别的命令)
图形界面操作的比較熟练。而且能够相应一部分的后台命令。
知道一些经常使用的配置文件的作用(如/etc/hosts、/etc/resolv.conf、/etc/passwd+、/etc/mtab等)
中级:
掌握一些高级的命令(如iftop、iptraf、rsync、ngrep、sar、acct、sg系列、inotail、nmap、lsof、ip、dig、wall、write、mkfs、grub系列、awk、sed、cron等)
熟悉一些高级配置文件的使用(如ld.conf)
熟悉proc、sys文件系统(进行诸如tcp调优等工作)
熟悉uevent(hotplug)、inotify等高级系统特性
懂得依据自己的需求配置编译内核,能够使用脚本编程
会使用iptables
高级:
能够掌握系统的高级特性。如安全的capability、suid、pam、lsm。如详细的kobject体系(能够通过查看sys文件系统代替经常使用的命令)。netfilter的hook使用和bpf(tcpdump)和ebpf的使用),进程的优先级调度(几种实时优先级和非实时优先级的设置)。oom分数的调整、cgroup
能够自由的选择使用高级的文件系统(如squashfs、gfs、ecryptfs、configfs等)
熟悉X系统、ssh(转发、反弹等高级操作)、socks、tcp wrapper等远程訪问相关
能够进行内核的高级定制编译(适当的改动内核代码。追踪解决内核bug)
能够编写基础的内核模块,使用经常使用的内核编程接口
懂得二进制原理(elf文件格式、objdump、ld、nm、strings等经常使用二进制软件的熟练使用)
各种bootloader的制作和安装

专家级:
此级别通常是专业方向。不是通用技能。系统的了解和预备知识的准备相同重要。比如tcp的深刻理解才会知道怎样做syn的ddos防护(不是内核的那个开关),对无线理论的深刻了解,才干搞无线的内核和应用内容。


内核虚拟化、内核存储逻辑(scsi、pci、usb等专一的和串联的)、无线子系统、音频子系统、显卡子系统、电源管理子系统、网络子系统、电源管理子系统

专家级之前的一般都要学会,工作中都会用到。这里的定级也限于对linux操作系统的使用,通常是软件和系统特性。也并没有涉及太多的编程要求。编程是另外的一个方面。编程能力不好不一定linux水平不行,所以这里的定级不怎么考虑编程水平。

学习方式

使用者

对linux的使用者实用来替代windows的普通桌面用户(如使用startos),可能原因是认为windows不好用。或者是感情问题。或者是版权问题,或者是为以后深入linux做平滑准备的。
也有命令使用者。

这部分人涵盖了非常多实际的工作岗位,典型的是运维。

运维有非常多细分的子岗位:系统管理,软件管理,后台server管理(比如数据库。http server),软件部署,安全等。

安全有时候划入运维,有时候单独列出。

所以。linux用好了就是能够当饭吃的。

桌面使用者

使用桌面能够鼠标点点即可,可是也能够用的非常销魂。

也有专门的职业工作就是怎么把桌面用起来。

比如嵌入式里的裁剪和启动桌面(让startx命令跑起来)。

普通桌面使用者

linux的桌面有非常多。普通的使用者通常会直接使用这几个桌面提供的环境和软件。

发行版

    发行版有非常多,通常是不同风格或者是服务于不同目的的专用发行版。常见的通用的发行版有:Ubuntu、opensuse、fedora、debian、Mandriva、mint、。

眼下ubuntu大有一统之势,越来越多的使用者和开发人员转向ubuntu,甚至server后端曾经经常使用的centos也在慢慢的丢失市场给ubuntu server。
    专用如kali(网络渗透)。puppy,lubuntu(精简),coreos,ubuntu core(虚拟化),router os(路由器)。这些专用发行版一般提供给专业用户,普通用户也能够使用,要发挥其全部威力。通常须要很多其它的行业知识。

桌面环境

    常见桌面环境有非常多:ubuntu的unity、gnome、kde、Cinnamon、mate、lxde、xfce。一般各个发行版都会携带不同的桌面魂晶,每一个桌面环境的窗体风格都是不一样的,还包含随桌面管理器携带的配套软件一般也是不一样的(比如计算器。包管理器,音乐播放器等)。可是有的流行的软件还是会被移植到不同的桌面管理器上。可是大部分没有。
    gnome、kde、unity的使用者最多。unity眼下仅仅用于Ubuntu。ubuntu也并非仅仅支持unity一种,差点儿全部的桌面环境ubuntu都有相应的支持版本号。unity的使用率随着ubuntu的普及而迅速上升。

高级桌面使用者

    高级的桌面使用者一般能够自由的选择不同的桌面环境,理解每一个桌面环境工作的原理,理解X系统,能够远程多终端使用X。自由的选择启动甚至不启动X或者X的一部分。

理解X和桌面管理器与窗体管理器的差别。

FrameBuffer

    framebuffer模式的显卡本身不具有不论什么运算数据的能力,他好比是一个临时存放水的水池.CPU将运算后的结果放到这个水池,水池再将结果 流到显示器.中间不会对数据做处理.在这中情况下,全部显示任务都有CPU完毕。CPU负担非常重.从frambuffer这个名字我们就能推測到他的功能 了(数据侦缓冲).
在linux内核中有有framebuffer机制,摹仿framebuffer显卡的这样的功能.他的优点是把显卡的硬件结构抽象掉。把全部的显卡都当做一个”水池”来用.应用程序也能够直接读取这个水池的内容.framebuffer的设备名是 /dev/fb
能够用命令:
#dd if=/dev/zero of=/dev/fb
清空屏幕.假设你的X用的是framebuffer的驱动,屏幕将全变黑.通过移动鼠标,切换窗体等动作能够让原先的内容又一次显示.
    假设你不用framebuffer驱动,能够在字符模式下做这个试验.屏幕将全部被清空.
以下的命令:
#dd if=/dev/fb of=fbfile
能够将fb中的内容保存下来,以后能够又一次写回屏幕:
#dd if=fbfile of=/dev/fb
作用相似于屏幕截图。可是截下的图不能用普通图片浏览器看.

    linux字符界面在高分辨率下,启动时会有一个小企鹅logo,这个logo就是用framebuffer功能写上屏幕的.

X

Linux内核给用户提供了显示frame buffer。全部要显示的东西写到buffer去就好了。也就是内核提供了显示的机制,可是没有提供显示的内容。所以显示内容须要 操作系统去实现。
差点儿全部的linux显示的核心都是X系统。X是一种显示协议,实现这个协议的经常使用软件是Xfree86、motif(商用),xorg、xnest等。

所以X也能够实如今windows中,苹果操作系统也是用的X。仅仅是是实如今内核中。

如今的发型版一般都默认使用xorg。好多人都看到x11这个词,X11R6 实际上是 X Protocol version 11 Release 6(X协议第11版第六次发行)的意思。

命令使用者

基础的命令完毕基础的功能

运维使用者

   运维人员能够说是最专业的linux使用者了,由于他们要关心linux整个系统的执行状况,是对linu系统的使用挖掘的最深的一群人。研发可能会更深入,可是一般不如运维的广度和挥洒自如。
   一个运维的基本功应该是查看系统状态的命令和脚本的编写,深入一些的运维对linux有非常深刻的了解。

命令

   运维经常使用的查看系统资源的命令有:
- 网络
- iftop:查看ip——ip的流量。还能够交互的查看port到port,以及进行过滤
- netstat(能够用ss替代)
- iptraf:图形化的观看ip流量
- nethogs
- tcpdump:抓包直接打印或者保存为pcap文件。甚至能够生成bpf代码
- ngrep:把网络数据包当成grep文件一样过滤。

高速查看网络数据的神器
- mascan:扫描器
- hscan:扫描器
- nmap:扫描器
- 内存
- vmstat
- io
- iostat:
- iotop
- 进程
- top:基础的进程查看工具。能够动态的查看进程的内存、cpu等系统资源。能够交互
- htop:增强的top,界面更美丽。功能也略多
- 其它:
- sar
- lsof
- acct
- monit
   一些方便的工具应用:
nping、incron(使用inotify机制,当文件发生变化时自己主动执行注冊脚本。相应于cron是基于时间的,incron基于文件事件)。rsync(远程文件同步)、inotial(不是轮训的tail,而是基于文件变化事件的tail)

机制

  • proc文件系统和sys文件系统是运维人员的提高篇,能够从 /proc/pid/以下的文件里看到在上述命令中看到的东西。从/proc/sys/中看到和改动系统当前的參数配置。

    从/sys/文件夹以下看到系统当前的物理资源(比如通过rotational文件来推断一个设备是否是ssd),

  • sys文件系统内部的kobject、ksystem、kset机制和uevent,hotplug、udev等要熟悉
  • 能够升级linux内核。熟练使用grub
  • 熟悉使用inotify、rsync、zk、ansible等基础设置软件进行公布和同步
  • 基于对scsi在linux的重要性的了解,了解sg系列命令的使用

脚本

一般的运维人员都会让自己的shell尽量的帅起来,比如使用guake。tmux,zsh等,还要熟练使用ssh远程管理系统,以及相关配置。通常大家都是编写bash脚本。
一般的,运维人员的cron和自己主动化脚本都是管理的每台机器必有的。

系统管理员

系统管理员与运维人员非常相似,只是运维一般出如今互联网企业,系统管理员一般出如今传统企业。一般的。系统管理员比运维更偏向于使用现有工具。而运维对系统的了解和脚本的使用更熟悉一些。

一般对升级内核要求不多,可是升级系统版本号还是有的。库的部署,部署环境(docker),解决环境问题。软件公布,配置管理等。
一般对etc下的配置文件都要非常熟
一个大头的工作非常可能是:修电脑。。。。

后台服务管理员

比如数据库管理员、http server、ntp、dns server、ftp server等各种常见的server的搭建和配置管理。

说起来easy。但每一个软件的配置文件都是一坨。详细阅读doc,多踩坑。祝君好运。

安全使用者

linux的安全系统发展至今非常全面,可是还是远远不够,linux距离一个安全的操作系统还有非常长的路要走。


- 在linux中的基础安全是UGO文件权限,对于进程的能力限制capbilities。


- 提高的是内核的安全框架lsm。以及在lsm下实现的各种防火墙,比如实现flask框架的selinux和apparmor。
- 还有针对文件的,mount文件系统的时候指定acl就能够针对文件进行訪问控制。还有开源的杀毒程序clamav
- 还有訪问控制模块pam,能够把进程的认证工作由程序猿转交给系统管理员

内核使用者

内核剪裁、编译、改动、移植
   内核的使用者多见于嵌入式开发和运维的内核升级。可是运维的内核升级一般涉及的功能裁剪较少,涉及的漏洞更新和功能增强较多。换句话说运维做内核是为了升级。嵌入式做内核是大部分为了降级。
   非常重要的一点,linux内核从2.6.30版本号開始,基本不适用于嵌入式系统。

尽管仍声称为嵌入式应用做了诸多优化,可是业界的嵌入式开发基本停步在2.6.30版本号的内核。你能够看到内核的新功能和增强基本都是为了互联网而产生的。而针对这样的内核进行裁剪也越来越难,甚至要高版本号的内核在嵌入式板子上跑起来这个主要的工作也越来越复杂。这也从側面反映出了互联网的活力和嵌入式行业的守旧。
   内核的裁剪工作最主要的不要求对内核怎样实现有太多的了解,可是须要知道内核实现的那些功能有什么,为何须要。比如你得现有net设备。之后net功能才是可选。而且net功能的繁多,一个嵌入式设备根本大部分不须要。内核的编译排版非常重要的一点是依照功能的层级划分的,而不是依照功能的重要性划分的。

比方你会发现无线系统里rfid,led。业余无线电和wifi是平级的,可是大部分人对前三者是不会使用的,仅仅须要wifi。可是内核的编译选项的组织并没有针对这样的需求上的流行程度进行优化。
   所以一个内核裁剪者须要知道差点儿全部内核选项的作用,最好多试试。至于针对改动。内核的实现大部分为了通用性,对效率和安全的考量是非常少的。假设你深入内核的代码层次的研究。你会发现内核的实现大部分在你使用的场景。你会有更优的算法。

你会想去又一次实现。可是,这里有一点linux内核最大的哲学:
内核的主要目的是抢占市场。


   所以。内核会覆盖尽可能多的功能,可是大部分功能的实现都不是企业级的。比如假设你的产品要支持打印机,你一般不会去用内核内置的功能,你会去购买更产品化的内核模块(比如kcodes),假设你的产品要支持samba,你会发现内核对ntfs的支持就是搞笑的,你还是会去购买商用的ntfs内核模块(商用的和开源的是同一个公司开发的)。

当你多关注内核的发展时。你会发现开源发展的最好的模块通常是企业支持的,而这背后一般有商用版本号存在。这就是内核的本质,出发点是开源的,共享的。发展是靠利益驱动的,繁荣则是全然靠商业的。相同的。商业又会阻碍内核的发展,所以感激尚存的为了理想而生活的程序猿。他们该开个账户,我们给他捐款。0….
   移植工作考验的大部分不是内核本身的技能,而是对gcc的了解程度。尤其是内核使用的Makefile系统。所以。想要做好嵌入式内核的移植工作。编译系统和连接的paper看一遍你基本就是大牛了。中国业界的大部分从业者。都不会去看的。我也不知道为啥,他们就是不去看。

开发人员

   开发人员就是传说中的程序猿。刚開始入门的程序猿通常会注重语法。helloworld就是这样的心态的典型写照。不同级别的程序猿用户的素养要求是不一样的。比如写业务代码,须要架构能力和编码标准。写高性能程序则须要数学。算法和高性能编程的硬件相关的知识。写实时代码又是须要另外一套理论体系。编程的语法是基础,可是编程的核心从来都不是语法。
   选择了一门好语言,基本就能确定你要用他来做的事情。

不存在万金油的语言。注重效率的和注重高速开发的。注重project管理,注重描写叙述问题的都不是相同的语言(当然你要用C做web开发我也没办法),甚至还存在专门处理字符串最牛逼的语言(perl)。对于linux来说,linux是个平台,开发高性能代码一般就得是asm,C和C++,须要性能和开发效率折中的能够有golang。脚本化的语言也是都能够用在linux上的,那取决于业务。
   单有语言写个hello world还能够,project编程最重要的是库。

就是代码的复用。一个成熟的程序猿和一个入门级的程序猿的最大差别不在于语法的熟练程度,在于架构能力和库的复用能力。
   所以,linux之于开发人员。不存在编程语言和库上的障碍。

基本上是内核所提供的功能上的。以及你怎样使用这样的功能(利用epoll、inotify等)

桌面应用开发人员

   linux下常见的桌面主要是kde和gnome。可是基本没人敢用他们开发工业产品。由于指不定哪天他们就没了。照眼下看来,gnome伴随着ubuntu的unity用户UI统一天下的概率非常大,说不定日后越来越多的厂商愿意为ubuntu的gnome开发图形界面的应用。

眼下linux上的产品级的应用的图形界面一般使用Qt,java(swing)等成熟的。可移植的图形库。


   所以眼下来看,假设你是桌面程序猿(andriod除外),你可能要用java和Qt的C++了。

由于andriod也是java,所以最划算的选择是用java(外国人对java有强大的热情,由于他是最早普及的工业化的编码语言,但不代表他是眼下最好的)。所以学习桌面应用开发基本上就是学习这两款产品的文档。

使用成熟库的后端开发人员

   后端开发人员占领了非常大一部分it开发就业比例(界面,站点。等前端开发人数最多。变化最快,技术沉淀最难),差点儿全部面向社会的程序都有后台server(非常多单机程序是没有的)。也是差点儿全部的后台server都要存储数据。

所以后台开发人员要面对的核心开发点就是:网络使用、传输编码、数据存储和多线程编程。至于后台设计的业务。在这4大模块来看差点儿能够忽略。所以后端开发技术要求比較高。而眼下的server差点儿被linux一统江湖了,这个趋势还会愈演愈烈,windows在这个领域基本没救了。


   今年golang在后端开发的流行度迅速崛起,可是大部分还是使用C/C++,python做后台开发也有相当大比例的份额(别说人家的效率不行,人家快,效率能够用钱买机器解决)。由于golang大部分使用自带的网络库,所以这节不关golang啥事了。


   网络经常使用的C/C++后端库是:原生的epoll、libevent、libev、boost::asio。ace。ace一般产业界没人用,较好不叫座。libev理论上比libevent高效,可是实际使用不见得。一般的工业级的开发都是使用libevent或者epoll,也有使用asio(比較少。由于C++难度高,大部分网络服务是C的)。
   传输编码问题,曾经是直接使用自己定义的格式或者自己定义的json后面加压缩,后来发展出了序列化。

再后来序列化进一步发展形成了protocolBuffer, thrift, avro等大公司主导的传输格式。眼下一般要用网络数据传输protocol buffer用的最多,thrift强势崛起,avro刚刚起步,可是特性不俗。
   数据存储问题。mysql差点儿是大小系统的第一选择。非常小的可能会使用sqlite,涉及到非IT大型企业可能用商用数据库比較多(自己不能开发,卖他的人又得赚钱)。nosql里mongodb用的比較多,可是近年各种nosql数据库千奇百怪。

有专门存放图的数据库,也有存储下载内容的分级的(rocksdb),也有存储地理信息的等等。

假设你是专业方向的开发人员,可能这些专门的数据库更适合你。
   多线程编程,在C/C++的世界里没有太多的选择。通常是pthread,C++能够用boost:thread或者C++11的thread,其后台也是pthread。pthread基本能够一统江湖。
   所以使用库的linux开发人员仅仅须要了解库的使用方法,当然对库后台是怎么调用操作系统详细实现的,能够了解也是非常好的。

系统级后端开发人员

   假设你打算看看你的发行版上装的那些莫名其妙的库是用来干嘛的。比如libncurses,libnss,libfuse等,而这些一般你平时开发应用程序都用不到。那么你基本做的就是系统级的后端开发了。系统开发与操作系统的关联非常大,学习系统开发就是在学习操作系统。


   系统开发对内核信息的获取要通过proc和sys。这是一定要熟练掌握的。这两个proc还比較easy,可是内容也非常多。sys则比較庞杂。内容很多其它。比如你得清楚的知道/proc/sys/kernel/core_pattern里面存的是core dump的路径。ulimit -c能够用来设置core的大小,默认是0.这些基础的背景知识以及整个文件系统衍生出来的知识点是系统级后端开发的基础。
   这些经常使用的开发内容包含:fifo文件,uevent,inotify,netlink。nice(实时进程),cpu亲和度,cgroup虚拟化。ptrace进程跟踪,子进程创建和控制,信号处理,文件锁。向量化的读写文件,文件描写叙述符操作,socket调用,epoll。文件与文件夹链接控制。锁。磁盘配额校验。进程记账,权限控制,执行优先级(io和cpu),低级port操作和sg直接发scsi命令,交换分区控制。pdflush,kswapd等内核进程的调优。模块的装载与卸载。内存映射与加锁,cache操作,直接的网络操作。用户管理,消息队列、信号量与共享内存等。
   系统级的后端开发直接是面向内核的使用,也就是系统级的开发人员基本就是内核的合格使用者。

运维开发人员

   运维开发人员比較接近于系统开发人员,可是运维开发人员比較多的使用cron命令,脚本,着重于系统资源的监控和划分。如今流行的devops比如ansible工具让运维与开发一气呵成。运维开发人员首先是一个运维使用者,运维系统比如全网监控系统。包公布系统,主机探測系统。域名系统等都是运维开发人员的方向。一个运维开发人员不做详细业务,也不是直接为详细业务服务,而是让详细业务能够专注于详细业务。
   一般的技能要求:经常使用运维命令,脚本。python

安全开发人员

   安全开发人员有两种。一种是怎样让自己开发的软件更安全,还有一种是就是开发安全防护软件。比如病毒扫描,防火墙,入侵检測,漏洞管理,权限控制等。

除了对安全使用者的技能的掌握外,还须要更深入的了解白帽子们的安全防护细节和原理。通常能防的人也能攻。不知道别人怎么攻就在防基本是瞎防。攻防是互动进步的。
   内核里有非常多针对安全开发的特性提供:内核加密接口和秘钥环、ASLR(进程启动栈随机化)、LSM机制。

做安全开发对系统本身的特性利用不大,对攻防手法的理解要求比較大。另外。防御系统通常是在业务的前面,所以要求低延时和高吞吐。所以基本上仅仅能使用C/C++(假设你见到哪个防火墙用python写的,麻烦给我膜拜一下)。
   所以安全开发的核心是业务和高效编程的能力。

而高效编程比如对dpdk、sse指令集的使用就是一个专门的学科了。业务就是安全相关的知识点。

应用后台开发人员

   大部分应用的后台就有两个要求:开发快,问题少。所以如今的市面上你会见到大把的时候golang、python甚至java做后台开发的案例。这样的形式的后台开发基本与操作系统无关,懂得主要的linux系统使用即可。

人们能够专注的面向业务。

内核开发人员

   内核开发人员的难度应该是最难的,假设谁提交了一个patch被内核接受了,那是非常了不起的事情。由于内核本身进展就非常大。而且内核开发没有市场上的职业相应,基本全靠偶然接触或者兴趣。职业最多的是驱动开发和内核裁剪小改动,另外文件系统开发和网络开发对内核也涉及到一些内核开发。由于内核的庞杂和耦合性比較重,学习本身就非常难了,更别说开发。可是假设你已经能够开发了。那非常多牛逼的开发就能够如探囊取物了,就像写一个C++程序那么顺手。

驱动开发人员

   驱动开发对uevent、kobject系统的了解需求比較多,明确udev程序和dev文件夹的工作原理。设备号的管理,主要的内存申请和使用。进阶的能够了解内核socket编程。进程的控制等。内核驱动的编程最主要的还是业务,要知道你控制的设备的寄存器和相应的总线在内核中的逻辑。

比如全部磁盘都是使用scsi命令,都要经过scsi层,usb。pci等总线的运作和内核接口的使用。

文件系统开发人员

   由于一切皆文件的思想,所以文件系统在linux中特别重要。

你得能够创建虚拟的设备,得学会利用dev下的设备,重要的,你得学会使用fd。这个fd就是简单的C里面open一个文件之后生成的那个,可是也是socket()之后生成的那个,由于是系统资源,所以fd是跨进程的,你仅仅要知道fd的号码,就能够在其它进程中直接使用。比方0,1,2(实际不是这个号码)号的fd就是输入输出和错误。

所以通过shell事实上能够做好多事情(O(∩_∩)O)
   内核层次的文件系统开发,必须得了解文件使用的整个流程,一切皆文件仅仅是最上面的vfs层。往下还有通用块层(在这里要进行重要的电梯算法),还要scsi层,要把对逻辑文件的訪问变为对物理存储訪问的命令,还要pci层。还要usb层。逻辑成真总要经过物理。所以物理协议实现的了解也是必须的。
   内核中提供了非常多默认的文件系统操作,非常多实现的文件系统都直接使用的默认的实现。有一类关键的文件系统是fuse,在用户端实现的。像个程序一样。这是内核为版权保护做的折中。

内核如今越来越多的倾向于把功能让给用户空间,大内核的思想在收缩。

由于开源的力量在一个点上确实不如商业高效。
   文件系统一般能够以模块的方式提供,能够非常easy也能够非常复杂。所以文件系统开发对内核的了解与其它差别不大。可是对文件系统本身有比較高的知识储备要求。

比如完整性校验,extends大块。磁盘配额,磁盘訪问控制acl,热插播。B+树等。

网络开发人员

   Linux内核本身的网络协议栈比較低效,可是能够应付绝大多数的使用情况。使用内核原生的协议栈时,通常是使用netfilter的hook。用内核的模块做一些事情。对内核代码本身的改动是不建议的。详细做安全还是包变换,有非常多netfilter的iptable本身就能够做。bpf更是提供了可编程的规则。

所以内核层面的网络开发核心是netfilter。


   对于有高性能要求的。一般有新浪的fastsocket和intel的dpdk这两种协议栈能够供选择。fastsocket眼下还不支持长连接,可是nginx这样的短连接应用会收益良多。

dpdk没有socket的概念。纯粹的包处理,而且是在用户空间,完美的支持多CPU和numa系统。所以你能够看到阿里。腾讯,谷歌,百度等都是用dpdk来做的网络。

原文地址:https://www.cnblogs.com/gccbuaa/p/7290838.html