linux的进程/线程/协程系列3:查看linux内核源码——vim+ctags/find+grep
linux的进程/线程/协程系列3:查看linux内核源码——vim+ctags/find+grep
- 前言
- 摘要:
- 1. 下载linux内核源码
- 2. 打标签方法:vim+ctags
- 2.1 安装vim
- 2.2 安装universal-ctags
- 2.3 查看源码
- 3. 系统命令:find+grep
- 3.1 find命令
- 3.2 grep命令
- 3.3 find+grep查找字符及源码
- 参考文献
前言
最近学习自动驾驶系统时,碰到协程的概念。进程和线程已经迷了,又来个协程,看了很多资料后决定作总结,概括三者联系和区别,最后归结到协程在自动驾驶中的应用。初级程序员目标是搞清三者概念并应用到实际中,而资深工程师则需要在系统层面考虑三者的性能及实现代价,直到如今三者仍是Linux内核和各类编程语言持续更新完善的模块之一,所以理清三者的关系、编程应用和考量性能是进阶程序员的必修课。行文的目的,是对进程/线程/协程这一系列繁复的概念和知识点做一个全面的总结,同时尽量做到知识点讲精讲细讲全,甄别模糊概念,同时兼顾源码及编程实现,最后归结到Apollo的协程实现。
本系列文章分九篇讲解:
- 《进程到协程的演化》:涉及进程发展的历史和计算机系统结构知识;
- 《进程/线程的系统命令》:总结进程/线程有关的系统命令,让大家有一个初步感性认识,而不只是生涩的文字;
- 《查看linux内核源码——vim+ctags/find+grep》:如何查看linux系统源码,源码第一手资料,重要性不言而喻;
- 《进程/线程相关知识总结》:进程/线程知识串讲,进程、线程和协程一脉相承,对进程理解透彻,线程和协程的难点也会迎刃而解。
- 《协程发展史、当前现状及libgo/tbox》:Conway Melvin如何总结出协同工作机制,引出当前协程库现状,分析它们的优劣势,并给出我的推荐:libgo,分析其源码目录。最后提引性能神器tbox。
- 《全面弄懂进程/线程/协程的内存调度》:三者在内存中的调度,,带读者领略内存调度的魅力。
- libgo/tbox功能及源码详解》:分析libgo/tbox的原理和集成功能,给出源码简读和样例。
- 《进程/线程/协程的性质辨析和实现对比》:列表分析三者的性质,同时根据源码,挑重点总结实现区别。
- 《Apollo中的协程概述》:协程在Apollo中的应用,展示及分析Apollo协程的源码及优缺点。
摘要:
本章讲解如何在系统中查看进程/线程的内核源码,为下一章方便查看实现方式差异做准备。本章分四节:第一节,讲解如何下载对应版本的内核源码源文件;第二节,使用vim+ctags查看源码;第三节,使用find+grep查看源码。
1. 下载linux内核源码
- 首先,查看自己的内核版本,命令如下:
$ apt-cache search linux-source
linux-source - Linux kernel source with Ubuntu patches
linux-source-4.15.0 - Linux kernel source for version 4.15.0 with Ubuntu patches
linux-source-4.18.0 - Linux kernel source for version 4.18.0 with Ubuntu patches
linux-source-5.0.0 - Linux kernel source for version 5.0.0 with Ubuntu patches
linux-source-5.3.0 - Linux kernel source for version 5.3.0 with Ubuntu patches
- 下载。目前最新只到5.3.0,所以选择它下载。这里的下载结果是将源码压缩文件放入/usr/src目录下对应版本目录,同时在/usr/src下创建一个软链接:
$ sudo apt install linux-source-5.3.0
/usr/src$ ll
total 32
drwxr-xr-x 8 shaw docker 4096 9月 26 18:43 ./
drwxr-xr-x 11 root root 4096 8月 7 2020 ../
drwxr-xr-x 7 root root 4096 9月 20 19:11 linux-headers-5.4.0-84-generic/
drwxr-xr-x 24 root root 4096 9月 20 19:11 linux-hwe-5.4-headers-5.4.0-84/
drwxr-xr-x 4 root root 4096 9月 19 20:04 linux-source-5.3.0/
lrwxrwxrwx 1 root root 45 7月 15 2021 linux-source-5.3.0.tar.bz2 -> linux-source-5.3.0/linux-source-5.3.0.tar.bz2
- 解压。我们需要对源码文件解压才能查看和进一步操作:
/usr/src$ tar xjvf linux-source-5.3.0.tar.bz2 -C ~/code/ ## 根据需要调整解压目录
下面我们看如何使用两种方式高效地查找源码。
2. 打标签方法:vim+ctags
vim+ctags虽然查找方便,格式简洁,但是只能查看打了tag的函数,如果查找没被打tag的函数或者某行代码是不行的,这时可以使用下一节的find+grep。下面分步骤讲解如何使用vim+ctags。
2.1 安装vim
vim安装直接使用命令即可:
$ sudo apt install vim
同时推荐一个vim配置,命令如下:
//这个会直接帮你配置vimrc和vim各种插件
$ wget -qO- https://raw.github.com/ma6174/vim/master/setup.sh | sh -x
2.2 安装universal-ctags
对于ctags,目前有两个版本,一个是exuberant-ctags,一个是universal-ctags。exuberant-ctags目前已停止维护,其原作者Reza Jelveh后来转投到universal-ctags旗下,所以推荐universal-ctags。其安装步骤如下:
- 安装autoconf,autoconf用于生成configure脚本:
$ sudo apt install autoconf
- 从github上克隆代码,可自选存放路径:
$ cd /tmp
$ git clone https://github.com/universal-ctags/ctags
- 安装universal-ctags,根据自己需要调整安装路径
$ cd /tmp/ctags
$ ./autogen.sh
$ ./configure --prefix=/opt/software/universal-ctags
$ make -j8
$ sudo make install
- 使用创建链接的方式,把新编译安装的universal-ctags链接过来:
$ sudo ln -s /opt/software/universal-ctags/bin/ctags /usr/bin/ctags
- 使用ctags生成tag:
$ cd ~/code/linux-source-5.3.0$ # 进入到之前的源码文件中
~/code/linux-source-5.3.0$ ctags -R . #递归地生成.tags文件
- 在vim中配置ctags,以便支持vim -t命令。在/etc/vim/vimrc加入配置:
$ sudo vim /etc/vim/vimrc
set tags=tags
set autochdirset tags+=/home/shaw/code/linux-source-5.3.0/tags
2.3 查看源码
以上就是vim+ctags的安装配置步骤,让我们试一下效果,比如查找源码中创建进程的函数fork:
~/code/linux-source-5.3.0$ vim -t fork
查找结果如下图所示,键入对应数字后回车即可进入相应文件查看,键入:q退出。
注意:因为生成的tag已配置在vim目录中,所以vim -t在任意目录均可查找。但find+grep只能在指定的目录中查找。
3. 系统命令:find+grep
find和grep是大家非常熟悉的两个linux系统命令,两者都是查找命令,但是有一些差别:find的查找对象是目录,返回结果是目录和文件名;而grep的查找对象是文件,返回结果是某行的字符串,而两者结合就可以搜索范围文件内的字符串。由于linux系统“一切皆文件”的特性,查找功能丰富的find和grep命令就显得尤为重要,下面简要介绍下两者用法:
3.1 find命令
find用来在指定目录下查找文件,并且将查找到的子目录和文件全部进行显示。find使用格式如下:
find [-H] [-L] [-P] [-D debugopts] [-Olevel] [path...] [expression]
其中[-H] [-L] [-P] [-D debugopts] [-Olevel]这几个选项并不常用,可以省略掉。path:find命令所查找的目录路径,例如用.来表示当前目录,用/来表示系统根目录。expression:可以分解为“-options [-print -exec -ok …],”,-options:指定find命令的常用选项,-print:将匹配的文件输出到标准输出,-exec:对匹配的文件执行该参数所给出的shell命令,-ok:和-exec的作用相同,不过在执行每一个命令之前,都会给出提示,让用户来确定是否执行 。options常用参数列举如下:
- -ipath p, -path p : 路径名称符合 p 的文件,ipath 会忽略大小写;
- -name name, -iname name : 文件名称符合 name 的文件,iname 会忽略大小写。可使用正则表达式,正则表达式的用法在grep中介绍;
- -size ±n : 文件大小是(无符号)大于(+)小于(-)n 单位,b 代表 512 位元组的区块,c 表示字元数,k 表示 kilo bytes,w 是二个位元组;
- -type d: 目录,c: 字型设备文件,b: 区块设备文件,p: 管道文件,f: 一般文件,l: 符号连结,s: socket;
- -user/group:根据文件所属用户或组来查找文件;
- -uid/gid:根据文件所属用户ID或组ID查找文件;
- -a,-o和–not:-a:and连接条件(两个同时满足);-o:or或条件;-not:取反;
- -atime,-mtime,-ctime,-amin,-mmin,-cmin,±n:根据文件时间戳的相关属性来查找文件,a/m/c表示最近一次访问/修改内容/修改属性;time单位为天,min单位为分钟;+n表示n time/min内没有做过a/m/c操作,-n表示n time/min内做过a/m/c操作。另外,我们可以通过stat命令来查看一个文件的时间信息;
- -depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找;
- -prune 使用这一选项可以使find命令不在当前指定的目录中查找,如果同时使用-depth选项,那么-prune将被find命令忽略;
- -perm:根据文件权限查找文件。r 读权限read 4;w 写权限write 2;x 操作权限execute 1。另外:文件权限格式为:【文件-或文件夹d】【owner权限】【group权限】【others权限】,如drwxrw-r–(767);
- -exec,xargs:-exec选项处理匹配到的文件时, find命令将所有匹配到的文件一起传递给exec执行。但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现溢出错误。而find命令把匹配到的文件传递给xargs命令,xargs命令每次只获取一部分文件而不是全部,不像-exec选项那样。这样它可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。 find命令配合使用exec和xargs可以使用户对所匹配到的文件执行几乎所有的命令。
下面列举几个例子:
- 将当前目录及其子目录下所有文件后缀为 .c 的文件列出来:
$ find . -name "*.c"
- 查找系统中所有文件长度为 0 的普通文件,并列出它们的完整路径:
$ find / -type f -size 0 -exec ls -l {} \; #{} \;为固定写法:一对大括号+空格+\+。
- 查找过去30天内名字为任意数字的没修改过内容的文件,并强制删除文件,包括目录:
$ find -mtime +30 -name "*[0-9]*" -exec rm –rf {} \; #等同于
$ find -mtime +30 -name "*[0-9]*" | xargs rm -f –r
- 查找系统中的每一个普通文件,通过管道过滤,然后使用xargs命令来测试它们分别属于哪类文件
$ find . -type f -print | xargs file
3.2 grep命令
Linux系统中grep命令 (Global search Regular Expression and Print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
基本格式如下:
grep [OPTIONS] PATTERN [FILE...]
上式中[OPTIONS]代表参数选项;PATTERN指定搜索模式,如果是简单字符串不需要引号,如果包含正则表达式,此时patter必须用单引号或双引号括起来,[FILE…] 即为要搜索的文件。
[options]主要参数:
- -?,–number:同时显示匹配行上下的number行
- -c,–count:只打印匹配的行数,不显示匹配的内容
- -i,–ignore-case:忽略大小写差别
- -h,–no-filename:当搜索多个文件时,不显示匹配文件名
- -q,–quiet:取消显示,只返回退出状态,0则表示找到了匹配的行
- -l,–files-with-matches:打印匹配模板的文件清单
- -L,–files-without-match:打印不匹配模板的文件清单
- -n,–line-number:在匹配的行前面打印行号
- -s,–silent:不显示关于不存在或者无法读取文件的错误信息
- -v,–revert-match:反检索,只显示不匹配的行
- -w,–word-regexp:把表达式做为一个单词搜索,而不是字符串的一部分
- -o :只显示被模式匹配到的字符串。
- –color :将匹配到的内容以颜色高亮显示。
下面再列出一些pattern正则表达式的元字符集(基本集):
- ^ :锚定行的开始,如’^grep’匹配所有以grep开头的行
- $:锚定行的结束,如’grep$'匹配所有以grep结尾的行
- .:匹配一个非换行符的字符 如’gr.p’匹配gr后接一个任意字符,然后是p
- *:匹配零个或多个先前字符 如’ *grep’匹配所有一个或多个空格后紧跟grep的行
- []:匹配一个指定范围内的字符,如’[Gg]rep’匹配Grep和grep。
- [^]:匹配一个不在指定范围内的字符,如:’[^A-FH-Z]rep’匹配不包含A-F和H-Z的一个字母开头,紧跟rep的行。
- (…):标记匹配字符,如:’(love)’,love被标记为1
- <:锚定单词的开始,如:’<grep’匹配包含以grep开始的单词的行
- >:锚定单词的结束,如’grep>'匹配包含以grep结尾的单词的行
- x{m}:连续重复字符x,m次,如’o{5}'匹配包含连续5个o的行
- x{m,}:连续重复字符x,至少m次,如’o{5,}'匹配至少连续有5个o的行
- x{m,n}:连续重复字符x,至少m次,不多于n次,如’o{5,10}'匹配连续5–10个o的行
- \w:匹配一个文字和数字字符,也就是[A-Za-z0-9],如’G\w*p’匹配以G后跟零个或多个文字或数字字符,然后是p
- \W:w的反置形式,匹配一个非单词字符,如点号句号等。\W*则可匹配多个
- \b:单词锁定符,如: '\bgrep\b’只匹配grep,即只能是grep这个单词,两边均为空格
下面举几个例子:
- 通过管道过滤ls -l输出的内容,只显示以a开头的行
$ ls -l | grep '^a'
- 显示所有以d开头的文件中包含test的行
$ grep 'test' d*
- 不区分大小写地搜索()默认情况区分大小写
$ grep -i pattern files
- 只列出匹配的文件名
$ grep -l pattern files
- 显示匹配pattern1或pattern2的行
$ grep pattern1 | pattern2 files
6.显示既匹配pattern1又匹配pattern2的行
$ grep pattern1 files | grep pattern2
3.3 find+grep查找字符及源码
有了上面知识的铺垫,就可以结合find和grep命令从特定文件查找特定字符。使用find查找特定文件,然后连接管道符号|,过滤文件内容,最后通过xargs将文件表作为输入参数传给grep,根据grep的模式定位到符合要求的文件的某行字符。举例如下:
- 用grep命令在目录/usr/include中搜索线程创建函数pthread_create。因为线程不属于linux的系统库,其原函数在/usr/include,指定目录也为了避免结果过多
find /usr/include -type f -print | xargs grep "pthread_create"
$ find /usr/include/ -type f -print | xargs grep "pthread_create"
/usr/include/thread_db.h: pthread_create(). */
/usr/include/thread_db.h: pthread_create(). */
/usr/include/pthread.h:extern int pthread_create (pthread_t *__restrict __newthread,
/usr/include/pthread.h:/* Get the default attributes used by pthread_create in this process. */
/usr/include/pthread.h:/* Set the default attributes to be used by pthread_create in this
/usr/include/c++/7/thread: // Create a reference to pthread_create, not just the gthr weak symbol.
/usr/include/c++/7/thread: auto __depend = reinterpret_cast<void(*)()>(&pthread_create);
- find+grep查找源码中的vsnprintf,如下所示。说明:(1)由于作者生成了tags,在tags中检索时产生很多无用信息,因此用-prune去掉tags;(2)-type f,即排除无用的目录;(3)注意,这里路径参数只能用完整路径,否则排除不掉;(4)检索printf和vsprintf时会有问题,虽然会搜索到对的文件,但是产生很多不匹配的行,而且行号显示也不对,可能和命令本身有关系,作者没弄清楚问题所在,知道的读者可以留言讨论;(5)命令后边可以跟>(创建文件并清空文件内容)或>>(在文件后追加)将搜索结果保存到文件。
$ find /home/shaw/code/linux-source-5.3.0 -path "/home/shaw/code/linux-source-5.3.0/tags" -prune -type f | xargs grep -n "vsnprintf" > rlt.txt
2778274:__color_vsnprintf tools/perf/util/color.c /^static int __color_vsnprintf(char *bf, size_t size, const char *color,$/;" f typeref:typename:int file:
3056917:color_vsnprintf tools/perf/util/color.c /^int color_vsnprintf(char *bf, size_t size, const char *color,$/;" f typeref:typename:int
4583419:vsnprintf drivers/acpi/acpica/utprint.c /^int vsnprintf(char *string, acpi_size size, const char *format, va_list args)$/;" f typeref:typename:int
4583420:vsnprintf lib/vsprintf.c /^int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)$/;" f typeref:typename:int
本章我们了解了如何查看进程和线程的源码。下一篇我们将初步介绍协程,包括协程历史、当前各协程库现状及优劣势分析。
本打算行文尽量简洁,但达不到讲精讲细的目的,所以我对本系列文章的定位是复杂知识点详细总结,在此基础上做到尽量简练。由于查阅了大量资料,耗费了很多精力,虽然谈不上尽善尽美,但也希望您的小手能支持作者一下,来个一键四联(点赞、收藏、评论、转发),希望帮助到不停探索的你。
参考文献
- Ubuntu16.04安装配置和使用ctags
- Ubuntu下查看Linux内核源码(vim+ctags)
- linux下find命令的使用和总结
- linux 中强大且常用命令:find、grep
linux的进程/线程/协程系列3:查看linux内核源码——vim+ctags/find+grep相关推荐
- Linux的进程/线程/协程系列4:进程知识深入总结:上篇
Linux的进程/线程/协程系列4:进程/线程相关知识总结 前言 本篇摘要: 1. 进程基础知识 1.1 串行/并行与并发 1.2 临界资源与共享资源 1.3 同步/异步与互斥 1.4 进程控制原语 ...
- linux的进程/线程/协程系列5:协程的发展复兴与实现现状
协程的发展复兴与实现现状 前言 本篇摘要: 1. 协同制的发展史 1.1 协同工作制的提出 1.2 自顶向下,无需协同 1.3 协同式思想的应用 2. 协程的复兴 2.1 高并发带来的问题 2.2 制 ...
- linux的进程/线程/协程系列1:进程到协程的演化
linux的进程/线程/协程系列1:进程到协程的演化 前言 摘要: 1. 一些历史:批处理时代 2. 现代操作系统启动过程 3. 进程(process)的出现 4. 线程(thread)与线程池 5. ...
- 简要说明__python3中的进程/线程/协程
多任务可以充分利用系统资源,极大提升程序运行效率,多任务的实现往往与 多线程,多进程,多协程有关 稳定性: 进程 > 线程 > 协程 系统资源占用量:进程 > 线程 > 协程 ...
- Python之进程+线程+协程(异步、selectors模块、阻塞、非阻塞IO)
文章目录 一.IO多路复用 二.selectors模块 本篇文字是关于IO多路复用的更深入一步的总结,上一篇 Python之进程+线程+协程(事件驱动模型.IO多路复用.select与epoll)对I ...
- 进程 线程 协程 各自的概念以及三者的对比分析
文章目录 1 进程 2 线程 3 进程和线程的区别和联系 3.1 区别 3.2 联系 4 举例说明进程和线程的区别 5 进程/线程之间的亲缘性 6 协程 线程(执行一个函数)和协程的区别和联系 协程和 ...
- linux进程线程协程的区别,进程和线程、协程的区别
现在多进程多线程已经是老生常谈了,协程也在最近几年流行起来.python中也有协程库,tornado中也用了gevent封装好的协程.本文主要介绍进程.线程和协程三者之间的区别. 一.概念 1.进程 ...
- 4.19 python 网络编程和操作系统部分(TCP/UDP/操作系统概念/进程/线程/协程) 学习笔记
文章目录 1 网络编程概念 1)基本概念 2)应用-最简单的网络通信 2 TCP协议和UDP协议进阶(网络编程) 1)TCP协议和UDP协议基于socket模块实现 2)粘包现象 3)文件上传和下载代 ...
- 并发编程:进程,线程,协程,异步
并发编程(不是并行)目前有四种方式:多进程.多线程.协程和异步. 多进程编程在python中有类似C的os.fork,更高层封装的有multiprocessing标准库 多线程编程python中有Th ...
最新文章
- 解决应用程序配置不正确,程序无法启动
- 在线浏览器录屏软件!妈妈再也不用担心我的windows找不到录屏软件啦!
- HTTP协议中的Content-Encoding
- 帆软报表多行多条数据写入表_在线报表FineReport中多数据集如何实现层式报表...
- 如何在 ASP.Net Core 中使用 SignalR
- MYSQL中的BlackHole引擎
- python3如何安装selenium_Mac-Firefox浏览器+selenium+Python3环境安装
- python_L2_operator
- 5.1 原型设计 - 页面流程图
- 麒麟810加持,华为nova 5z让你一步从青铜变王者
- 如果要在mFC客户区添加控件怎么办
- pyqtSignal信号和槽
- 牛客网Java笔试题目
- 如何使用分区工具实现无损分区大小调整?
- Cnetos linux镜像全版本2.X、3.X、4.X、5.X、6.X、7.X、8.X
- 在Windows下搭建WAMP环境
- matlab画贝塞尔曲线给出图题,matlab练习程序(贝塞尔曲线)
- printf 和 puts
- 计算机上键盘无法输入法,为什么键盘打不出字 大家都会用鼠标点击输入法图...
- linux系统深度评测,真国产,深度linux系统评测第二集
热门文章
- python3中求0-100的和
- Nodejs服务器端处理POST提交的数据_note
- kafka 主动消费_Kafka消费组(consumer group)
- 报错日常——Tomcat45秒超时问题
- mybatis mysql5.7_【mysql】mysql5.7支持的json字段查询【mybatis】
- java代码ftp重命名未生效_java实现FTP远程文件移动(重命名、复制、拷贝) | 学步园...
- java8 stream多次map_java8streamapi:如何将列表转换为在列表中具有重复键的MapLong,Set?...
- 博途软件中多重背景块的建立_如何正确的理解西门子博途中的—单个实例和多重实例的区别...
- python与jupyter关系,Ipython,jupyter和kernels是什么关系?
- sql server datetime取年月_快速定位数据库性能问题,RDS推出慢SQL统计分析