一个程序员的思考

一个关于程序员水平的思考

img

很多程序员可能听说过一句话:“Talk is cheap, show me the code”。 是的,这句话就是linux操作系统的缔造者Linus Torvalds说出来的。他本人的成就这里不去描述,实在描述不过来。用网上的一句话就是“他用了50年的时间达到了别人几辈子都无法企及的高度”。

​ 这句话,其实很好理解:口说无凭,把你的成果拿出来一看便知。也许你是大牛,这在你的代码上能很好的体现,不用多说我们也能看出来。如果你是一个水平很low或者一般的攻城狮,可能口才很棒,说话水平一流,但是你的代码如果一般,那么我们也会认为你不是一个合格的程序员。 这用在程序员身上是很容易理解的,而且程序员更注重代码水平,口才不是排在第一位的。

​ 举个自己的亲身体会吧:

​ 我以前偶尔(也没那么偶尔)看到别人写的开源代码,因为我主要是做网络方向的,这部分的开源代码基本都是C语言实现的(例如各种通信协议)。C语言的基础我的水平也算是熟悉的阶段(没人敢谈精通),看基本的语法是没什么问题的,偶尔来几个个性的写法确实看不懂(比如说signal函数实现、container_of实现等、… …),但是说一个完整的项目功能,不可能完全是这个晦涩的语法的堆积,因此在语法上基本都是可以看懂的。那么问题来了,只看的懂语法,不知道人家在做什么,实现什么功能该怎么办? 也许会有人问:“既然能看得懂语法,你怎么可能不知道人家在干什么?”。 这个问题确实是存在的,我们在看得懂人家的代码的基础上要学习人家的思想:为什么这个实现? 其他的方式不行吗?这实现的好处是什么? 当然这一连串的问题可能需要我们花费比较长的时间一个个来思考。这所有的一切的前提都是能看懂人家的代码。

​ 还是这个问题“如何才能看得懂人家的代码”?

​ 我们只拿C语言来说话,因为这个最基础,很多人在大学都接触过。 它的语法说句实话,不是很多。也许函数接口比较多,但是我们经常用的却是比较少的,比如:IO类(read, write,close,open…),进程类、线程类、IPC类、网络通信类(TCP、UDP函数接口)、IO复用等。这部分函数我们一般都会接触到或者经常用到,可以说比较熟。但是,对,是但是,它们我们也许只是看着很熟悉,它们的用法真的熟悉吗?举几个例子:

  • TCP能使用sendto发送数据吗?SYN包能携带数据吗?
  • select, poll, epoll函数的区别是什么?(面试可能经常遇到)
  • 为什么要线程分离?
  • 常见的信号类型及处理方式;信号进程屏蔽字

这些有一部分是我之前的疑问,有一些是看开源代码是自己思考的。我们不是看不懂人家的语法,而是对这个基础知识理解太浅,虽然基础知识很少,但是每一个点都是值得深究的。不是说拿起课本直接开始啃,而是遇到一个学习一个(最最常用的那些其实也没那么多)。在举个例子:

​ 我们都知道IO多路复用中的select和poll函数。select函数有个不好的地方:它监控的描述符有限(可能是1024左右),而且监控越多效率多低。而我在看openswan代码的时候就遇到一个用法:他们自己实现了struct fd_set以及对应的操作函数FD_SET, FD_ISSET, FD_ZERO等,然后在select调用时,使用他们自己的fd_set类型。他们的基本用法我知道,但是是否可以自己定义类型、修改后是否能用等我之前并不知道。也许这个问题并不影响我们对这个代码的理解,也许这就是我们与他们存在的一个小小的差距。

​ 接着上述的问题,我们再说select和poll的一个例子:(我只用openswan中的原话)

/* Even though select(2) says that there is a message,
* it might only be a MSG_ERRQUEUE message.  At least
* sometimes that leads to a hanging recvfrom.  To avoid
* what appears to be a kernel bug, check_msg_errqueue
* uses poll(2) and tells us if there is anything for us
* to read.
*
* This is early enough that teardown isn't required:
* just return on failure.
*/
if (!check_msg_errqueue(ifp, POLLIN))

这个使用的情形是:通过select函数监控所有的网口的一个端口(500),当其中有读事件准备好时,select函数返回执行上面的代码。但是select可能返回的是一个“MSG_ERRQUEUE”,而这个错误会导致读阻塞,因此再使用poll函数检查是否存在上述“MSG_ERRQUEUE”。说句实话,这种用法我第一次遇到,也是对select、poll不熟导致的吧。

​ 看源码还有个难点就是:他们的数据结构之间的组织关系。这部分没有什么技术上的难点,但是逻辑上、实现上让我怀疑人生的感觉。

​ 我们与大神级程序员的差别也许就在那些基础知识的理解深度上,同样的两个人:一个普通程序员、一个微软Google等的高级程序员,对待同一个功能实现,可能基本的函数接口相同,但是他们考虑的情况很多、程序的健壮性、鲁棒性更好。这不仅仅是他们遇到这类情况多,另一个原因可能是他们知道使用那些接口会遇到什么样的问题,然后再使用另一种方式来进行弥补、检测。

在这里插入图片描述

​ 也许Linux很普及、也许Nginx功能很强大、也许VPN很安全、也许网络发展的很快很快。但他们都是用C语言支撑起来的。

​ 也许C语言很容易入门。但它真的很难。

​ 也许程序员吃的真是青春饭。

原创文章 96 获赞 73 访问量 6万+

猜你喜欢

转载自blog.csdn.net/s2603898260/article/details/105858742