最近学习自动驾驶系统时,碰到协程的概念。进程和线程已经迷了,又来个协程,看了很多资料后决定作总结,概括三者联系和区别,最后归结到协程在自动驾驶中的应用。初级程序员目标是搞清三者概念并应用到实际中,而资深工程师则需要在系统层面考虑三者的性能及实现代价,直到如今三者仍是Linux内核和各类编程语言持续更新完善的模块之一,所以理清三者的关系、编程应用和考量性能是进阶程序员的必修课。行文的目的,是对进程/线程/协程这一系列繁复的概念和知识点做一个全面的总结,同时尽量做到知识点讲精讲细讲全,甄别模糊概念,同时兼顾源码及编程实现,最后归结到Apollo的协程实现。
本系列文章分九篇讲解:
$ 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
$ 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/ ## 根据需要调整解压目录
下面我们看如何使用两种方式高效地查找源码。
vim+ctags虽然查找方便,格式简洁,但是只能查看打了tag的函数,如果查找没被打tag的函数或者某行代码是不行的,这时可以使用下一节的find+grep。下面分步骤讲解如何使用vim+ctags。
vim安装直接使用命令即可:
$ sudo apt install vim
同时推荐一个vim配置,命令如下:
//这个会直接帮你配置vimrc和vim各种插件
$ wget -qO- https://raw.github.com/ma6174/vim/master/setup.sh | sh -x
对于ctags,目前有两个版本,一个是exuberant-ctags,一个是universal-ctags。exuberant-ctags目前已停止维护,其原作者Reza Jelveh后来转投到universal-ctags旗下,所以推荐universal-ctags。其安装步骤如下:
$ sudo apt install autoconf
$ cd /tmp
$ git clone https://github.com/universal-ctags/ctags
$ cd /tmp/ctags
$ ./autogen.sh
$ ./configure --prefix=/opt/software/universal-ctags
$ make -j8
$ sudo make install
$ sudo ln -s /opt/software/universal-ctags/bin/ctags /usr/bin/ctags
$ cd ~/code/linux-source-5.3.0$ # 进入到之前的源码文件中
~/code/linux-source-5.3.0$ ctags -R . #递归地生成.tags文件
$ sudo vim /etc/vim/vimrc
set tags=tags
set autochdir
set tags+=/home/shaw/code/linux-source-5.3.0/tags
以上就是vim+ctags的安装配置步骤,让我们试一下效果,比如查找源码中创建进程的函数fork:
~/code/linux-source-5.3.0$ vim -t fork
查找结果如下图所示,键入对应数字后回车即可进入相应文件查看,键入:q退出。
注意:因为生成的tag已配置在vim目录中,所以vim -t在任意目录均可查找。但find+grep只能在指定的目录中查找。
find和grep是大家非常熟悉的两个linux系统命令,两者都是查找命令,但是有一些差别:find的查找对象是目录,返回结果是目录和文件名;而grep的查找对象是文件,返回结果是某行的字符串,而两者结合就可以搜索范围文件内的字符串。由于linux系统“一切皆文件”的特性,查找功能丰富的find和grep命令就显得尤为重要,下面简要介绍下两者用法:
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常用参数列举如下:
下面列举几个例子:
$ find . -name "*.c"
$ find / -type f -size 0 -exec ls -l {} \; #{} \;为固定写法:一对大括号+空格+\+。
$ find -mtime +30 -name "*[0-9]*" -exec rm –rf {} \; #等同于
$ find -mtime +30 -name "*[0-9]*" | xargs rm -f –r
$ find . -type f -print | xargs file
Linux系统中grep命令 (Global search Regular Expression and Print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
基本格式如下:
grep [OPTIONS] PATTERN [FILE...]
上式中[OPTIONS]代表参数选项;PATTERN指定搜索模式,如果是简单字符串不需要引号,如果包含正则表达式,此时patter必须用单引号或双引号括起来,[FILE…] 即为要搜索的文件。
[options]主要参数:
下面再列出一些pattern正则表达式的元字符集(基本集):
下面举几个例子:
$ ls -l | grep '^a'
$ grep 'test' d*
$ grep -i pattern files
$ grep -l pattern files
$ grep pattern1 | pattern2 files
6.显示既匹配pattern1又匹配pattern2的行
$ grep pattern1 files | grep pattern2
有了上面知识的铺垫,就可以结合find和grep命令从特定文件查找特定字符。使用find查找特定文件,然后连接管道符号|,过滤文件内容,最后通过xargs将文件表作为输入参数传给grep,根据grep的模式定位到符合要求的文件的某行字符。举例如下:
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(&pthread_create);
$ 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
本章我们了解了如何查看进程和线程的源码。下一篇我们将初步介绍协程,包括协程历史、当前各协程库现状及优劣势分析。
本打算行文尽量简洁,但达不到讲精讲细的目的,所以我对本系列文章的定位是复杂知识点详细总结,在此基础上做到尽量简练。由于查阅了大量资料,耗费了很多精力,虽然谈不上尽善尽美,但也希望您的小手能支持作者一下,来个一键四联(点赞、收藏、评论、转发),希望帮助到不停探索的你。