Linux C/C++编程FAQ系列 之一

Posted by c4pr1c3 on November 17, 2010

这个FAQ系列的基础是我之前所带的一个Linux下C开发项目的内部Wiki,在可以预期的一段时间内,我仍将在Linux C/C++开发项目管理和培训上持续实践着。所以,我决定在我的blog上定期更新这个FAQ,方便所有Linux C/C++开发新手和进阶选手的快速学习和查阅。

  1. man手册页的阅读
  2. 关于正则表达式
  3. 多线程编程
  4. null和NULL怎么区别?应该用哪个?
  5. glib和glibc之间的关系


什么是man手册

首先,man是manual的简称,中文说法可以是手册。 许多Linux的新手经常会因为一些命令的使用或函数的使用不清楚而发帖求助,老鸟们在回帖的时候一般都喜欢用“man XXX”来回复。于是,新手在终端上敲入了man XXX,然后屏幕上出现了密密麻麻的英文。。。

这些英文实际上是最好的帮助和说明文档,下面用一个man的手册页截图为例来说明man手册的基本组成。

man strcmp


上面的是一个API函数strcmp的man手册页,首先注意到左上角括号里的数字3是这个手册页所属的section标记,关于section的说明,请往下看。 这个手册页由这几个部分组成:

NAME

这是命令的名字和简单的解释,显然,要调用这个函数要使用它的名称。

SYNOPSIS

是摘要部分,在这里给出的是函数所在的头文件和函数声明原型。

DESCRIPTION

函数的详细说明。

RETURN VALUE

返回值解释说明

CONFORMING TO

遵循的语言规范。

SEE ALSO

相关的其他函数。

如果是命令的man手册页,结构上会有所不同,一般来说命令的手册页会有OPTIONS一节,对命令的所有参数进行解释,有些命令还有附带的EXAMPLES方便理解。

除此之外,以mkdir的man手册页为例:

mkdir [OPTION] DIRECTORY...

上面的方括号内的参数是可选的,而没有方括号包围的参数则是必填参数,如这里的DRIRECTORY。而后面的…表示DIRECTORY参数可以多次出现,即有多个DIRECTORY参数

man手册的基本结构

man手册页的结构
Section 名称 说明
1 用户命令 可由任何人调用的程序或工具
2 系统调用 内核提供的函数API接口
3 API 用户态函数API接口
4 设备 /dev目录下的特殊文件
5 文件格式描述 如/etc/passwd
6 游戏
7 杂项 例如宏命令包,惯例等
8 系统管理工具 root调用的程序或工具
9 其他(Linux特定的) 用来存放内核例行程序的文档
n 新文档 可能要移到更适合的领域
o 老文档 可能会在一段期限内保留
l 本地文档 与本特定系统有关的

man手册基本使用

  1. 简单查询
man

man printf
  1. 按节查询
man

前面已经说过,man手册页是按照手册页的内容进行分类的。所以,就会存在同一个关键词在不同节出现的情况。对于这种多次出现的关键词,我们就需要进一步缩小检索范围。比如open,既是一个用户命令,也是一个系统调用,甚至还是Perl的一个函数。所以我们在进行查找的时候就有必要加上section标识,如查找open的系统调用说明,就使用

man 2 open
  1. 模糊查询 有时,我们想查询一个关键词的man手册页,但是不知道这个关键词的完整名称或者这个关键词根本就没有man手册页,但是有其他格式的帮助文档。这时候,就可以通过以下命令来进行查找:
man -k

上面的命令等价于apropos,关于apropos这个命令有什么用,就自己man去吧o(∩_∩)o

以open为例,在man手册页里有多节内容是关于open的,如果我们不清楚我们要查询的open到底在哪一节里出现,就可以用下面的命令进行查询:

man -a

4.退出man

q

5.在手册页内查找

只要会用vim的人,就会在man里面进行查找。/进入查找模式,输入关键词,回车。n或p向后或向前查找。

6.在手册页内翻页

除了方向键和PageUP、PageDown,还可以使用空格(后翻一页)、回车(后翻一行)来进行翻页操作。如果你更习惯vim的操作方式,那就尽情的jk吧。

在Vim中查看man手册

光标置于要查询的函数名称上,K直接调用man命令查询当前光标处的函数名的man帮助。有些关键字,例如printf,我们通常要查询的是位于第3节的C语言里printf的函数帮助文档。这个时候,我们可以光标置于要查询的函数名称上,3K直接调用man -3 命令查询当前光标处的函数名的man帮助。

还有不明白的地方?

man man

如果说Google搜索引擎是全人类学习进步的探照灯,那么man手册页就是所有*nix使用者的手电筒。虽不如探照灯的光线强烈和深远,但强在伸手即得,随时可用。

man -a regcomp

关于正则表达式的基础知识,可以参考Mastering Regular Expressions 3ed.chm。另外,The GNU C Library.chm中的Pattern Matching一章也有关于GNU C的正则表达式使用讲解。

man -a pthread_create
man -a pthread_join
man -a pthread_self
man -a pthread_detach
man -a pthread_exit
  • 基本的线程操作包括:线程创建、结束、同步(join,阻塞)、调度、数据管理和进程间通信
  • 在NPTL线程模型中,一个线程在创建了一批线程之后并不会维护所创建线程的信息,同样的,没有“父线程”的概念。
  • 一个进程中的所有线程共享一个进程地址表空间。
  • 同一个进程中的所有线程共享
    • 进程中的指令代码
    • 打开的文件描述符
    • 信号和信号处理函数
    • 当前工作路径(环境变量)
    • 用户和组id
  • 每个线程独立拥有
    • 线程ID
    • 函数的栈顶指针(函数的返回地址)和相关的栈内存空间(函数内的局部变量)
    • 信号掩码
    • 线程优先级
    • 错误返回代码:errno
  • 所有线程相关的操作函数的返回值都用“0”表示OK

推荐Beginning.Linux.Programming 3rd.pdf 的第12章 POSIX Threads

首先,提出这个问题的程序员,一般都有过其他编程语言的经历和背景。在Java和Javascript程序员来看,null都是语言规范中定义好的,用来表示“空对象”(注意:Javascript中null是表示“空值”,undefined才是“空对象”)。在C/C++中,我们只有NULL。 接下来要搞清楚在C和C++语言里,NULL其实有着不同的宏定义。你问我依据在哪儿?OK,看/usr/include/stdio.h,注意到以下代码:

# define __need_NULL
# include < stddef.h >

跟入,我们看到以下代码:

undef NULL
if defined(__cplusplus)
define NULL 0
else
define NULL ((void *)0)
endif

到此,我们就应该很清楚了NULL在实际代码中使用的注意事项了。

GLib is a general-purpose utility library, which provides many useful data types, macros, type conversions, string utilities, file utilities, a main loop abstraction, and so on. It works on many UNIX-like platforms, Windows, OS/2 and BeOS. GLib is released under the GNU Library General Public License (GNU LGPL). The general policy of GLib is that all functions are invisibly threadsafe with the exception of data structure manipulation functions, where, if you have two threads manipulating the same data structure, they must use a lock to synchronize their operation.

GLib是Gtk +库和Gnome的基础。GLib可以在多个平台下使用,比如Linux、Unix、Windows等。GLib为许多标准的、常用的C语言结构提供了相应的替代物。 GLib中定义了好多有用的数据结构,如单(双)向连表,可变长的数组等,线程池等有用的东西。使用GLib库的程序都应该包含GLib的头文件glib.h。

GLIBC The GNU C library is primarily designed to be a portable and high performance C library. It follows all relevant standards (ISO C 99, POSIX.1c, POSIX.1j, POSIX.1d, Unix98, Single Unix Specification). It is also internationalized and has one of the most complete internationalization interfaces known.

Glibc 是提供系统调用和基本函数的 C 库,比如open, malloc, printf等等。所有动态连接的程序都要用到它。是GNU开发的C库。 他们之间在用途上没有太大关系。