Linux内核代码风格
Linux Kernel Coding Style
a g e1ContentsLinux Kernel Coding Style (Linux 内核代码风格) (2)Chapter 1: Indentation (缩进) ............................................................................................ 2 Chapter 2: Breaking long lines and strings (把长的行和字符串打散) ..................................... 4 Chapter 3: Placing Braces (大括号和空格的放置) ............................................................ 4 3.1 Spaces (空格) ................................................................................................................ 6 Chapter 4: Naming (命名) .................................................................................................. 8 Chapter 5: Typedefs .................................................................................................................. 9 Chapter 6: Functions (函数) ............................................................................................. 11 Chapter 7: Centralized exiting of functions (集中的函数退出途径) ...................................... 12 Chapter 8: Commenting (注释) ............................................................................................... 13 Chapter 9: You've made a mess of it (你已经把事情弄糟了) ................................................ 15 Chapter 10: Kconfig configuration files (Kconfig 配置文件) ................................................ 16 Chapter 11: Data structures (数据结构) ................................................................................. 17 Chapter 12: Macros, Enums and RTL (宏,枚举和RTL ) .................................................. 18 Chapter 13: Printing kernel messages (打印内核消息) .......................................................... 19 Chapter 14: Allocating memory (分配内存) ........................................................................... 20 Chapter 15: The inline disease (内联弊病) ............................................................................. 21 Chapter 16: Function return values and names (函数返回值及命名) ................................... 22 Chapter 17: Don't re-invent the kernel macros (不要重新发明内核宏) ............................... 23 Chapter 18: Editor modelines and other cruft (编辑器模式行和其他需要罗嗦的事情) ..... 24 Appendix I: References .. (24)a g e2Linux Kernel Coding Style (Linux 内核代码风格)This is a short document describing the preferred coding style for the linux kernel. Coding style is very personal, and I won't _force_ my views on anybody, but this is what goes for anything that I have to be able to maintain, and I'd prefer it for most other things too. Please at least consider the points made here.这是一个简短的文档,描述了linux 内核的首选代码风格。
linux系统基础知识
linux系统基础知识Linux系统基础知识Linux是一种自由和开放源代码的类Unix操作系统,它是由Linus Torvalds在1991年首次发布的。
Linux系统具有高度的可定制性和灵活性,因此在服务器、超级计算机、移动设备等领域得到了广泛的应用。
本文将介绍Linux系统的基础知识,包括Linux的发行版、文件系统、用户和权限、命令行和图形界面等方面。
一、Linux的发行版Linux系统有许多不同的发行版,每个发行版都有自己的特点和用途。
常见的Linux发行版有Ubuntu、Debian、Fedora、CentOS、Red Hat等。
这些发行版都是基于Linux内核开发的,但它们的软件包管理、安装方式、默认桌面环境等方面有所不同。
选择适合自己的Linux发行版可以提高工作效率和使用体验。
二、文件系统Linux系统的文件系统采用树形结构,根目录为/。
在根目录下有许多子目录,如bin、etc、home、usr等。
其中,/bin目录存放系统命令,/etc目录存放系统配置文件,/home目录存放用户的主目录,/usr目录存放系统软件和库文件等。
Linux系统支持多种文件系统,如ext4、NTFS、FAT32等。
文件系统的选择取决于使用场景和需求。
三、用户和权限Linux系统是一个多用户系统,每个用户都有自己的用户名和密码。
用户可以通过命令行或图形界面登录系统,并执行各种操作。
Linux 系统采用权限控制机制,每个文件和目录都有自己的权限。
权限分为读、写、执行三种,分别对应数字4、2、1。
文件和目录的权限可以通过chmod命令进行修改。
Linux系统还有超级用户root,拥有系统的最高权限,可以执行任何操作。
四、命令行Linux系统的命令行界面是其最基本的界面,也是最强大的界面。
通过命令行可以执行各种操作,如创建文件、修改权限、安装软件等。
Linux系统的命令行界面有许多命令,如ls、cd、mkdir、rm、chmod等。
linux 内核编译编译选项
1.Code maturity level options代码成熟等级。
此处只有一项:prompt for development and/or incomplete code/drivers,如果你要试验现在仍处于实验阶段的功能,就必须把该项选择为Y了;否则可以把它选择为N。
2. Loadable module support对模块的支持。
这里面有三项:Enable loadable module support:除非你准备把所有需要的内容都编译到内核里面,否则该项应该是必选的。
Set version inFORMation on all module symbols:可以不选它。
Kernel module loader:让内核在启动时有自己装入必需模块的能力,建议选上。
3. Processor type and featuresCPU类型。
有关的几个如下:Processor family:根据你自己的情况选择CPU类型。
High Memory Support:大容量内存的支持。
可以支持到4G、64G,一般可以不选。
Math emulation:协处理器仿真。
协处理器是在386时代的宠儿,现在早已不用了。
MTTR support:MTTR支持。
可不选。
Symmetric multi-processing support:对称多处理支持。
除非你富到有多个CPU,否则就不用选了。
4. General setup这里是对最普通的一些属性进行设置。
这部分内容非常多,一般使用缺省设置就可以了。
下面介绍一下经常使用的一些选项:Networking support:网络支持。
必须,没有网卡也建议你选上。
PCI support:PCI支持。
如果使用了PCI的卡,当然必选。
PCI access mode:PCI存取模式。
可供选择的有BIOS、Direct和Any,选Any 吧。
Support for hot-pluggabel devices:热插拔设备支持。
Linux 汇编语言开发指南
二、Linux 汇编语法格式绝大多数 Linux 程序员以前只接触过DOS/Windows 下的汇编语言,这些汇编代码都是 Intel 风格的。
但在 Unix 和 Linux 系统中,更多采用的还是 AT&T 格式,两者在语法格式上有着很大的不同:1.在 AT&T 汇编格式中,寄存器名要加上 '%' 作为前缀;而在 Intel 汇编格式中,寄存器名不需要加前缀。
例如:2.在 AT&T 汇编格式中,用 '$' 前缀表示一个立即操作数;而在 Intel 汇编格式中,立即数的表示不用带任何前缀。
例如:3.AT&T 和 Intel 格式中的源操作数和目标操作数的位置正好相反。
在Intel 汇编格式中,目标操作数在源操作数的左边;而在 AT&T 汇编格式中,目标操作数在源操作数的右边。
例如:4.在 AT&T 汇编格式中,操作数的字长由操作符的最后一个字母决定,后缀'b'、'w'、'l'分别表示操作数为字节(byte,8 比特)、字(word,16 比特)和长字(long,32比特);而在 Intel 汇编格式中,操作数的字长是用 "byte ptr" 和 "word ptr" 等前缀来表示的。
例如:5.在 AT&T 汇编格式中,绝对转移和调用指令(jump/call)的操作数前要加上'*'作为前缀,而在 Intel 格式中则不需要。
6.远程转移指令和远程子调用指令的操作码,在 AT&T 汇编格式中为"ljump" 和 "lcall",而在 Intel 汇编格式中则为 "jmp far" 和 "call far",即:7.与之相应的远程返回指令则为:8.在 AT&T 汇编格式中,内存操作数的寻址方式是section:disp(base, index, scale)而在 Intel 汇编格式中,内存操作数的寻址方式为:section:[base + index*scale + disp]由于 Linux 工作在保护模式下,用的是 32 位线性地址,所以在计算地址时不用考虑段基址和偏移量,而是采用如下的地址计算方法:disp + base + index * scale下面是一些内存操作数的例子:三、Hello World!真不知道打破这个传统会带来什么样的后果,但既然所有程序设计语言的第一个例子都是在屏幕上打印一个字符串 "Hello World!",那我们也以这种方式来开始介绍 Linux 下的汇编语言程序设计。
Linux的特点及发展趋势
5.支持多种硬件平台的操作系统
从普通的PC机到高端的超级并行计算机系统,都可以运行Linux系统。 Linux符合IEEE POSIX标准,特别注重可移植性,使Unix下的许多应用程 序可以很容易地移植到Linux平台上,相反也是这样。
6.完整的开发平台
Linux支持一系列的开发工具,几乎所有的主流程序设计语言都已移 植到Linux上,并可免费得到,如 C、C++、PASCAL、Java、Perl、PHP、 Fortran、ADA等。
2013年9月11日星期三
3
间受到很大的限制。在这种情况下,我们不能不为中国软件产业的前途 担忧。 如果我们国家整个信息系统(包括电子政务、电子商务、军事网络 以及互联网等系统)是建立在这样一个平台上,那么我们的政治、经济、 安全等利益如何能得到保障? 为了摆脱这种困境,我们需要有一个自主的操作系统平台。20世纪 80年代,我国曾试图开发过多种操作系统(如COSIX),但后来均因为 缺乏应用软件的支持而没有成功。其实,那时美国IBM公司也曾开发过 一个名为OS/2的操作系统,当时其技术水平甚至超过了微软公司同期的 版本,但同样因为缺乏应用软件,不得不以失败告终。可见,作为服务 器和桌面计算机应用的通用操作系统并不是短期可以成熟的。任何公司、 任何国家,不管投入有多大,要想在短时间里做出一个成熟的通用操作 系统是不现实的。 正当人们为摆脱软件垄断而一筹莫展时,Linux等开放源码软件给我 们带来了希望。Linux系统源代码开放的特点,使得对于安全要求较高的 应用可以认真检查、修改其源代码满足特殊应用需求,而丰富的应用软 件又可以避免前车之鉴。
2.
强大的图形操作界面
Linux系统有着功能强大的图形操作界面,其外观和操作与Microsoft Windows系列非常类似,熟悉Windows操作的用户可以很快掌握其操作方 法。但从技术上来看,Linux操作系统的图形界面与Microsoft Windows系 列有着本质的不同,它是从Unix平台上X Window发展而来,称为XFree86, 这一技术的特点是图形系统分为服务器和客户端两
想要成为Linux底层驱动开发高手这些技巧绝对不能错过
想要成为Linux底层驱动开发高手这些技巧绝对不能错过对于想要成为Linux底层驱动开发高手的人来说,掌握一些关键技巧是非常重要的。
本文将介绍一些不能错过的技巧,帮助读者提升自己在Linux底层驱动开发领域的能力。
1. 深入理解Linux内核:在成为Linux底层驱动开发高手之前,你需要对Linux内核有深入的理解。
了解内核的基本概念、代码结构和内核模块之间的关系是非常重要的。
阅读Linux内核的源代码、参与内核邮件列表的讨论以及阅读相关的文献资料都是提升自己技能的好途径。
2. 熟悉底层硬件知识:作为底层驱动开发者,你需要熟悉底层硬件的工作原理。
这包括了解处理器架构、设备的寄存器操作、中断处理等。
掌握底层硬件知识可以帮助你编写高效、稳定的驱动程序。
3. 学习使用适当的开发工具:在Linux底层驱动开发中,使用适当的开发工具是非常重要的。
例如,使用调试器可以帮助你快速定位驱动程序中的问题。
掌握使用GCC编译器、GNU调试器(GDB)和性能分析工具(如OProfile)等工具可以提高你的开发效率。
4. 阅读相关文档和源代码:Linux底层驱动开发涉及到大量的文档和源代码。
阅读设备供应商提供的文档、Linux内核源代码以及其他相关文献资料可以帮助你更好地了解特定设备的工作原理和使用方法。
5. 编写清晰、高效的代码:编写清晰、高效的代码对于成为Linux底层驱动开发高手是至关重要的。
使用良好的编码风格、注释和命名规范可以提高代码的可读性。
此外,了解Linux内核的设计原则和最佳实践也是编写高质量驱动程序的关键。
6. 多实践、调试和优化:在实际开发过程中,积累经验是非常重要的。
通过多实践、调试和优化不同类型的驱动程序,你可以更好地理解Linux底层驱动开发的技巧和要点。
此外,学会使用内核调试工具和性能分析工具可以帮助你提高驱动程序的质量和性能。
7. 参与开源社区:参与开源社区是成为Linux底层驱动开发高手的好方法。
C语言GNU扩展语法
GNU C 9条扩展语法GNC CC是一个功能非常强大的跨平台C编译器,它对标准C语言进行了一系列扩展,以增强标准C的功能,这些扩展对优化、目标代码布局、更安全的检查等方面提供了很强的支持。
本文把支持GNU扩展的C语言称为GNU C。
Linux内核代码使用了大量的GNU C扩展,以至于能够编译Linux内核的唯一编译器是GNU CC,以前甚至出现过编译Linux内核要使用特殊的GNU CC版本的情况。
本文是对Linux内核使用的GNU C扩展的一个汇总,希望当你读内核源码遇到不理解的语法和语义时,能从本文找到一个初步的解答,更详细的信息可以查看。
文中的例子取自Linux 2.4.18。
1、零长度和变量长度数组组长度为1,分配时计算对象大小比较复杂。
3、语句表达式GNU C把包含在括号中的复合语句看做是一个表达式,称为语句表达式,它可以出现在任何允许表达式的地方,你可以在语句表达式中使用循环、局部变量等,原本只能在复合语句中使用。
例如:复合语句的最后一个语句应该是一个表达式,它的值将成为这个语句表达式的值。
这个定义计算x和y分别两次,当参数有副作用时,将产生不正确的结果,使用语句表达式只计算参数一次,避免了可能的错误。
语句表达式通常用于宏定义。
4、typeof 关键字使用前一节定义的宏需要知道参数的类型,利用typeof可以定义更通用的宏,不必事先这里typeof(x)表示x的值类型,第3行定义了一个与x 类型相同的局部变量_x 并初使化为x,注意第5行的作用是检查参数x和y的类型是否相同。
typeof 可以用在任何类型可以使用的地方,通常用于宏定义。
5、可变参数宏这里arg表示其余的参数,可以是零个或多个,这些参数以及参数之间的逗号构成arg 的值,在宏扩展时替换arg,例如:使用##的原因是处理arg不匹配任何参数的情况,这时arg的值为空,GNU C预处理器在这种特殊情况下,丢弃##之前的逗号,这样扩展为注意最后没有逗号。
源程序书写格式
源程序书写格式尽管 C 语言在语法规定上对书写格式没有严格的限制,但是源程序的排版格式应当遵从多数程序员的惯例,以便于程序的维护。
许多同学可能受中文单词间不需要空格的影响以及 C 语言教科书中未对书写格式提出建议,导致书写的 C 语言源程序缺少必要的空格,密密麻麻的语法元素拥挤在一起,阅读起来需要首先“断词”。
按照惯例应当添加适当的空格,断开相关的“语法单词”。
下面列举出书写方面应注意的几个问题。
后面两页附上的源代码样例节选于 Linux 的源程序文件 ping.c ,源代码样例的每行都带有行号,对书写方面应注意的问题提供了实际例子的参考行号。
附表1 C 语言源程序书写格式建议花括号的书写风格有两种:if (xxxxx) {yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy} else {zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz}if (xxxxx) { yyyyyyyyyyyyyyy zzzzzzzzzzzzzzzz } else { zzzzzzzzzzzzzzzz zzzzzzzzzzzzzzzz }第一种风格起源于早期 UNIX 的内核源代码,即 C 语言诞生的地方;第二种风格起源于 Pascal 程序员 begin/end 关键字的书写习惯向 C 语言的转变。
目前,在 Microsoft 世界和 Linux 世界中,两种书写风格都很常见,第一种风格略占上风。
无论选择哪种风格必须做到同一个源程序文件中一致,不要两种风格混用。
变量和函数命名方法也有两种风格。
一种是匈牙利命名法(源自 Microsoft 的一位匈牙利籍天才程序员),如:SendAckFrame ;另一种方法为传统的下划线分割法,如:send_ack_frame 。
同一个源程序文件中的命名风格应做到一致。
1 static int in_cksum(unsigned short *buf, int sz)2 {3 int nleft = sz;4 int sum = 0;5 unsigned short *w = buf;6 unsigned short ans = 0;78 while (nleft > 1) {9 sum += *w++;10 nleft -= 2;11 }1213 if (nleft == 1) {14 *(unsigned char *)&ans = *(unsigned char *)w;15 sum += ans;16 }1718 sum = (sum >> 16) + (sum & 0xFFFF);19 sum += (sum >> 16);20 ans = ~sum;21 return ans;22 }2324 static void unpack(char *buf, int sz, struct sockaddr_in *from)25 {26 struct icmp *icmppkt;27 struct iphdr *iphdr;28 struct timeval tv, *tp;29 int hlen, dupflag;30 unsigned long triptime;3132 gettimeofday(&tv, NULL);3334 /* check IP header */35 iphdr = (struct iphdr *) buf;36 hlen = iphdr->ihl << 2;3738 /* discard if too short */39 if (sz < (datalen + ICMP_MINLEN))40 return;4142 sz -= hlen;2243 icmppkt = (struct icmp *) (buf + hlen);44 if (icmppkt->icmp_id != myid)45 return; /* not our ping */4647 if (icmppkt->icmp_type == ICMP_ECHOREPLY) {48 nreceived++;49 tp = (struct timeval *) icmppkt->icmp_data;5051 if ((_usec -= tp->tv_usec) < 0) {52 _sec--;53 _usec += 1000000;54 }55 _sec -= tp->tv_sec;5657 triptime = _sec * 10000 + (_usec / 100);58 tsum += triptime;59 if (triptime < tmin)60 tmin = triptime;61 if (triptime > tmax)62 tmax = triptime;6364 if (TST(icmppkt->icmp_seq % MAX_DUP_CHK)) {65 nrepeats++;66 nreceived--;67 dupflag = 1;68 } else {69 SET(icmppkt->icmp_seq % MAX_DUP_CHK);70 dupflag = 0;71 }7273 if (options & O_QUIET)74 return;7576 printf("%d bytes from %s: icmp_seq=%u", sz,77 inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr),78 icmppkt->icmp_seq);79 printf(" ttl=%d", iphdr->ttl);80 printf(" time=%lu.%lu ms", triptime / 10, triptime % 10);81 if (dupflag)82 printf(" (DUP!)");83 printf("\n");84 }85 }。
linux 开发新驱动步骤
linux 开发新驱动步骤Linux作为一款开源的操作系统,其内核源码也是开放的,因此,许多开发人员在Linux上进行驱动开发。
本文将介绍在Linux上进行新驱动开发的步骤。
第一步:确定驱动类型和接口在进行驱动开发前,需要确定驱动类型和接口。
驱动类型包括字符设备驱动、块设备驱动、网络设备驱动等。
接口包括设备文件、系统调用、ioctl等。
根据驱动类型和接口的不同,驱动开发的流程也有所不同。
第二步:了解Linux内核结构和API驱动开发需要熟悉Linux内核的结构和API。
Linux内核由许多模块组成,每个模块都有自己的功能。
API是应用程序接口,提供了许多函数和数据结构,开发人员可以使用这些函数和数据结构完成驱动开发。
第三步:编写驱动代码在了解了Linux内核结构和API后,就可以编写驱动代码了。
驱动代码需要按照Linux内核的编码规范编写,确保代码风格统一、可读性好、可维护性强等。
在编写代码时,需要使用API提供的函数和数据结构完成相应的功能。
第四步:编译驱动代码和内核模块驱动代码编写完成后,需要编译成内核模块。
编译内核模块需要使用内核源码中的Makefile文件。
编译完成后,会生成一个.ko文件,这个文件就是内核模块。
第五步:加载和卸载内核模块内核模块编译完成后,需要加载到Linux系统中。
可以使用insmod命令加载内核模块,使用rmmod命令卸载内核模块。
在加载和卸载内核模块时,需要注意依赖关系,确保依赖的模块已经加载或卸载。
第六步:调试和测试驱动开发完成后,需要进行调试和测试。
可以使用printk函数输出调试信息,在/var/log/messages文件中查看。
测试时需要模拟各种可能的情况,确保驱动程序的稳定性和可靠性。
Linux驱动开发需要掌握Linux内核结构和API,熟悉驱动类型和接口,按照编码规范编写驱动代码,并进行编译、加载、调试和测试。
只有掌握了这些技能,才能进行高效、稳定和可靠的驱动开发。
GNU编程风格
Linux作为GNU家族的一员,上面的源代码数以万计,而在阅读这些源代码时我们会发现,不同的源代码的美观程度和编程风格都不尽一样,有些代码,如glibc 的代码:static voidrelease_libc_mem (void){/* Only call the free function if we still are running in mtrace mode. */if (mallstream != NULL)__libc_freeres ();}或者是Linux核心的代码:static int do_linuxrc(void * shell){static char *argv[] = { "linuxrc", NULL, };close(0);close(1);close(2);setsid();(void) open("/dev/console",O_RDWR,0);(void) dup(0);(void) dup(0);return execve(shell, argv, envp_init);}都令人看起来赏心悦目,而其它有些程序员写的程序则让人看起来直皱眉头,写作干净美观的代码,不仅仅使得代码更容易阅读,还使得代码能够成为一件艺术品。
同微软的匈牙利命名法一样,在Linux上编程主要有两种编程风格: GNU风格和Linux核心风格,下面将分别介绍。
GNU编程风格下面几条是基于GNU开放源代码方面的要求:1.在任何情况下都不要引用有版权的源代码。
2.善意接受别人给您的程序添加的代码,但请记住检查其合法性,即是否也是 GNU 的。
3.编写日志文件(Changelog),这将使您的代码更容易维护。
下面是GNU对C程序的风格要求:1.函数的开头的左花括号放到最左边,避免把任何其它的左花括号、左括号或者左方括号放到最左边。
对于函数定义来说,把函数名的起始字符放到最左边也同样重要。
of_parse_phandle源码解析_概述说明
of_parse_phandle源码解析概述说明1. 引言1.1 概述本文将对Linux内核中的of_parse_phandle函数进行源码解析,并对其实现细节、性能优化考虑以及可读性优化建议等进行讨论。
of_parse_phandle函数是Open Firmware(OF)机制下用于处理设备句柄的一个重要函数,它可以解析设备节点中的phandle属性,找到对应的设备句柄并返回。
1.2 文章结构文章主要分为五个部分:引言、of_parse_phandle源码解析、实现细节分析、of_parse_phandle源码优化思路以及结论与展望。
在引言部分,将对这篇长文的背景和整体结构进行介绍;在of_parse_phandle源码解析中,我们将详细说明函数的功能、源码解析要点以及使用示例;接着,在实现细节分析部分,将深入探讨解析逻辑、数据结构和错误处理机制;然后,在of_parse_phandle源码优化思路中,将提出一些建议,包括性能优化考虑、可读性优化建议和其他改进方向探讨;最后,在结论与展望里,总结当前工作并展望未来需要进一步研究的内容。
1.3 目的本文旨在通过对of_parse_phandle函数的源码解析,帮助读者深入理解该函数的功能和实现细节。
同时,通过对源码的优化思路探讨,提供一些有益的建议来改善该函数的性能和可读性。
通过本文的阅读,读者将能够更好地使用和理解of_parse_phandle函数,并在需要时进行相应的优化工作。
以上是文章“1. 引言”部分的内容,如果您需要进一步撰写其他部分或有其他问题,请随时告诉我。
2. of_parse_phandle源码解析:2.1 功能介绍:of_parse_phandle是Linux内核中的一个函数,用于解析设备树中的phandle 属性。
phandle属性主要用于在设备树中表示设备节点之间的连接关系,通过phandle可以唯一标识一个设备节点。
of_parse_phandle函数在使用时,根据提供的参数解析设备树中的phandle属性,并返回对应的设备节点引用。
linux 编译告警关闭参数-概述说明以及解释
linux 编译告警关闭参数-概述说明以及解释1.引言1.1 概述在软件开发过程中,编译告警是指在将源代码编译成可执行文件的过程中,编译器检测到的潜在问题或错误的提示信息。
这些告警信息对于开发人员来说非常重要,因为它们可以帮助我们发现并修复代码中的潜在问题,提高代码的质量和稳定性。
然而,并非所有的编译告警都是严重的问题,有时候可能会产生一些误报或者仅仅是一些警告。
对于一些项目来说,这些警告可能会增加开发成本,而且有时候更关注的是能够成功编译和运行代码。
因此,在某些情况下,有必要关闭一些编译告警,以减少开发人员的工作量。
本文将介绍如何关闭Linux编译告警的参数,并提供一些建议和注意事项,帮助开发者在实际项目中正确处理编译告警。
尽管关闭编译告警可能会有一定的风险,但我们可以通过选择性关闭一些特定的告警,来确保代码的正常编译和运行,同时降低不必要的开发成本。
在接下来的章节中,我们将首先讨论Linux编译告警的意义,以及为什么我们需要关注这些告警。
然后,我们将列举一些常见的Linux编译告警,了解它们可能的原因和解决方案。
最后,我们将介绍一些关闭Linux编译告警的常用参数,并提供一些注意事项,以帮助开发者正确地使用这些参数,并在必要的时候关闭一些特定的告警。
1.2 文章结构本文主要分为三个部分:引言、正文和结论。
在引言部分,我们将对本文进行概述,明确文章的目的和意义,并介绍文章的整体结构。
正文部分将重点探讨Linux编译告警相关的内容。
首先,我们将提到Linux编译告警的意义,说明为什么我们需要关注和处理这些告警信息。
其次,我们将列举一些常见的Linux编译告警,分析它们的原因和可能的解决方案,以帮助读者更好地理解这些告警的含义和影响。
结论部分将总结全文,并给出关闭Linux编译告警的参数和相关注意事项。
我们将提供一些可行的解决方案,以便读者根据自己的实际情况选择合适的关闭参数,并注意一些可能的副作用和风险。
Linux教程第7章 C语言开发工具
第7章C语言开发工具实验目的●学习理解Linux环境中将C程序转换成可执行文件所经历的过程●学习使用Linux环境中将C程序转换成可执行文件所采用的命令●学习使用indent、gcc、make、gdb命令实验指导Linux操作系统提供了非常好的编程环境,Linux系统支持多种高级语言。
C语言是Linux中最常用的系统编程语言之一,Linux内核绝大部分代码是用C语言编写的,Linux 平台上的相当多的应用软件也是用C语言开发的。
使用C语言,软件开发人员可以通过函数库和系统调用非常方便实现系统服务。
另外,还有很多有用的工具为程序开发和维护提供便利。
Linux操作系统拥有许多用于程序的生成以及分析的软件工具。
其中包括用于编辑和缩进代码、编译与连接程序、处理模块化程序、创建程序库、剖析代码、检验代码可移植性、源代码管理、调试、跟踪以及检测运行效率等等的工具。
在这一章里,我们将介绍一些常用的C语言工具,主要包括gcc、make工具。
make工具可以用来跟踪那些更新过的模块,并确保在编译时使用所有程序模块的最新版本。
7.1 编写程序的工具我们编写程序可以用Linux文本编辑器(如:pico编辑器、vi编辑器、gedit编辑器、emacs 编辑器和xemacs编辑器)。
我们首先使用vi 编辑器来编辑hello.c,这是一个C 语言的文件。
$ vi hello.c输入下列程序代码:#include <sdtio.h>#include <sdtlib.h>int main(){int i,j;for (i=0,j=10; i < j; i++){。
KR风格VSMS风格
KR风格VSMS风格(1)书写结构k&r风格: 缩进⼀个⽔平制符,k&r提倡8格.左花括号紧接其后不另起⼀⾏(函数体的左括号除外). if(...) {...;...;} else if(...) {...;...;} else {...;...;}while(...) {...;...;}do {...;...;}while(...);for(...;...;...) {...;...;}typedef {...;...;...;}abc;class abc {...;...;...;};ms vc++风格: 缩进⼀个⽔平制符,vc的⽔平制符相当4个空格.if(...){...;...;}else if(...){...;...;}else{...;...;}while(...){...;...;}do{...;...;}while(...);typedef{...;...;...;}abc;class abc{...;...;...;};坚持k&r风格的开发⼈员认为将左花括号单独占⼀⾏浪费了⾏数,使代码稀疏不够紧凑.只要右花括跟条件控制关键字if,while,do,for等并列即已很清晰.缩进制表符相当于8个空格,这样层次清晰,4格不够清晰.坚持ms风格的开发⼈员认为左花括号紧接其后不另起⼀⾏⽽函数体的左括号却另起⼀⾏,是⼀种怪异的不⼀致性.缩进8格太多,缩进层次多了会使⼀些代码跑出屏幕.(2)命名法k&r风格: 讲究简短清爽.单词⼀致使⽤⼩写;⼀个单词超过8个字符的使⽤缩写;⼀个名字中包含多个单词则⽤下划线隔开它们.BOOL empty;int num_element;void get_element();class stack;class seq_stack;struct student;object obj;dialog dlg;int object::cls_id;int tmp;int i, j;ms风格: 讲究表意明确.使⽤匈⽛利法给名字加类型前缀;每个单词第⼀个字母以⼤写开头;相对前者更容易冗长,也有少部分地⽅借鉴于k&r风格.BOOL bIsEmpty;int dwNumberOfElements;void GetElement();class IStack;class CSequenceStack;struct SStudentInfo;CBaseObject cBaseObject;CBaseDialog cBaseDialog;int CBaseObject::m_dwClassID;//也有少部分借鉴于k&r的简约风格int tmp;int i, j;坚持ms风格的⼈认为k&r风格的变量,结构和很多标识符出现在⼀起时,有时⼈会分不清标识符是函数内的成员还是普通变量,或者不知道变量,结构还是类.坚持k&r风格的⼈认为微软的所谓"表意明确"和匈⽛利类型命名法是纯粹⾃找脑损伤的表现.好的名字本来就不应该让程序员看不懂是什么类型.⼜何尝要加匈⽛利类型前缀,并讽刺匈⽛利类型前缀是写给编译器看的.(3)总结k&r风格,历史悠久,⽽且有众多友好的开源兄弟,如linux内核风格,gnu编码规范,它们都跟k&r基本相同.如果要写开源代码,使⽤k&r可能会更受⼈欢迎.不少坚持k&r风格的开发⼈员认为k&r风格是⽼字号,是C语⾔发明⼈提出国际标准化组织制定的风格.因此⼀些开发者认为ms风格不够正统.ms风格是这⼏年推向MS外部开发⼈员的后起之秀,凭着微软的软件巨⽆霸的实⼒,迅速风靡开来.随着Visual C++,MFC在开发市场推⼴和普及,越来越多的开发⼈员逐渐接受了ms风格.不少坚持ms风格的开发⼈员认为k&r风格已过时,编程规范应该与时俱进.noncopyable功能同意程序轻松实现⼀个不可复制的类。
完整版Linux内核代码风格
.. } else if (x > y) {
... } else {
.... } 理由:K&R。 也请注意这种大括号的放置方式也能使空(或者差不多空的)行的数量最小化,同时不失可读性。因此,由于你的屏 幕上的新行的供应不是可回收的资源(想想 25 行的终端屏幕),你将会有更多的空行来放置注释。 当只有一个单独的语句的时候,不用加不必要的大括号。 if (condition) action(); 这点不适用于本身为某个条件语句的一个分支的单独语句。这时需要在两个分支里都使用大括号。 if (condition) { do_this(); do_that(); } else { otherwise(); } 3.1:空格 Linux 内核的空格使用方式(主要)取决于它是用于函数还是关键字。(大多数)关键字后要加一个空格。值得注意的 例外是 sizeof、typeof、alignof 和__attribute__,这些关键字某些程度上看起来更像函数(它们在 Linux 里也常常伴随小 括号而使用,尽管在 C 语言里这样的小括号不是必需的,就像“struct fileinfo info”声明过后的“sizeof info”)。 所以,在这些关键字之后放一个空格: if, switch, case, for, do, while 但是不要在 sizeof、typeof、alignof 或者__attribute__这些关键字之后放空格。例如: s = sizeof(struct file); 不要在小括号里的表达式两侧加空格。这是一个反例: s = sizeof( struct file ); 当声明指针类型或者返回指针类型的函数时,“*”的首选使用方式是使之靠近变量名或者函数名,而不是靠近类型名。 例子: char *linux_banner; unsigned long long memparse(char *ptr, char **retptr); char *match_strdup(substring_t *s); 在大多数二元和三元操作符两侧使用一个空格,例如下面所有这些操作符: = - < > * / % | & ^ <= >= == != ? : 但是一元操作符后不要加空格: & * - ~ ! sizeof typeof alignof __attribute__ defined 后缀自加和自减一元操作符前不加空格: -前缀自加和自减一元操作符后不加空格: -“.”和“->”结构体成员操作符前后不加空格。 不要在行尾留空白。有些可以自动缩进的编辑器会在新行的行首加入适量的空白,然后你就可以直接在那一行输入代
四种操作系统的区别
四种操作系统的区别操作系统是计算机系统中的核心组成部分,它负责管理计算机硬件和软件资源,使得计算机能够高效地运行。
在计算机领域中,存在着多种不同类型的操作系统。
本文将分别介绍四种常见的操作系统——Windows、Mac、Linux和iOS,并对它们的区别进行详细阐述。
一、Windows操作系统Windows操作系统是由美国微软公司开发的一系列图形化操作系统。
作为最常用的操作系统之一,Windows具有以下几个特点:1. 图形化界面:Windows操作系统采用直观的图形用户界面(GUI),使得用户可以通过鼠标点击、拖拽等操作完成各项任务,操作简单便捷。
2. 软件支持:Windows系统有着丰富的软件和应用程序,用户可以轻松安装和使用各种办公、娱乐、设计等软件,满足个人和商业需求。
3. 兼容性:Windows操作系统具有很高的硬件兼容性,支持各种品牌和型号的计算机设备,易于扩展和升级。
4. 广泛应用:Windows操作系统在个人电脑、笔记本电脑、服务器等设备上广泛应用,是许多用户的首选系统。
二、Mac操作系统Mac操作系统是由美国苹果公司开发的一种操作系统,专门用于苹果公司的硬件设备。
相较于其他操作系统,Mac操作系统拥有以下独特特点:1. 稳定与安全:Mac操作系统基于Unix内核,具有较高的稳定性和安全性,减少了受到病毒和恶意软件攻击的风险。
2. 用户体验:Mac操作系统注重用户体验,采用直观的GUI和简洁的设计风格,让用户感受到良好的操作界面和平滑的动画效果。
3. 高性能硬件:Mac操作系统与苹果公司自家的硬件设备相结合,如iMac、MacBook等,能够充分发挥硬件性能,提供更流畅的操作和更高的效率。
4. 专业软件:Mac操作系统广泛应用于创意行业,如音视频编辑、图形设计等,配套的专业软件如Final Cut Pro、Logic Pro等能够满足专业需求。
三、Linux操作系统Linux操作系统是一种开源免费的操作系统,由全球的开发者共同维护和改进。
几种编程风格简介
⼏种编程风格简介⾯向对象,⾯向过程,函数式编程,声明式编程都是⼀种编程风格:⼀、函数式编程lisp就是⼀种抽象程度很⾼的编程范式,纯粹的函数式编程语⾔编写的函数没有变量,模拟数学上的函数,,任意⼀个函数,只要输⼊是确定的,输出就是确定的,这种纯函数我们称之为没有副作⽤。
函数式编程的特点就是,允许把函数本⾝作为参数传⼊另⼀个函数,还允许返回⼀个函数!不会修改外部参数或变量的值精简可读性差python 不是⼀个完全意义上的函数式编程语⾔,只是引⽤了函数式编程的风格⽐如 map reduce filter 匿名函数python 是允许使⽤变量的程序设计语⾔,由于函数内部的变量状态不确定,同样的输⼊,可能得到不同的输出,因此,这种函数是有副作⽤的,可能会修改外部参数或变量的值。
以后学习进程,线程时函数式编程就会引起改变外部变量的问题.⼆、⾯向过程的编程思想:流⽔线式的编程思想,在设计程序时,需要把整个流程设计出来优点:体系结构更加清晰简化程序的复杂度缺点:可扩展性及其的差⾯向过程编程的应⽤场景是:不需要京城变化的软件如 linux 内核 httpd,git等⾯向过程的编程与函数式编程的关系:函数是Python内建⽀持的⼀种封装,我们通过把⼤段代码拆成函数,通过⼀层⼀层的函数调⽤,就可以把复杂任务分解成简单的任务,这种分解可以称之为⾯向过程的程序设计。
函数就是⾯向过程的程序设计的基本单元。
三、声明式编程:列表表达式⽣成器对象和列表解析都是将⼀系列代码封装到⼀⾏赋给⼀个变量,是⼀种编程的⽅式四、⾯向对象的编程只是解决了代码的可扩展性的问题特点:对象之间交互的结果不能确定可扩展性强可控性差应⽤场景:需求经常变化的⽤户层,互联⽹应⽤,游戏等。
网络操作系统Linux简介
学习目标
1,了解Linux操作系统的发展历程,现状及未来以及 Linux操作系统下的常用软件. 2,理解Linux操作系统的内核版本和发行版本. 3,掌握Linux操作系统的功能和特性, Linux操作系 统的内核体系结构.
学习重点
Linux操作系统的内核版本和发行版本;Linux操作系 统的内核体系结构.
3.1 Linux的发展 的发展
3.1.1什么是Linux
Linux是一种主要适用于个人计算机的类似于Unix风格的操作 系统.它的独特之处在于不受任何商品化软件的版权制约, 全世界都能免费,自由使用.它支持多用户,多进程,多线 程,实时性好,功能强大而稳定.它的出现为我们带来了计 算机上突破性的创举. Linux之所以受到广大计算机爱好者的喜爱,主要原因有两个, 一是它属于自由软件,用户不用支付任何费用就可以获得它 和它的源代码,并且可以根据自己的需要对它进行必要的修 改,无偿对它使用,无约束地继续传播.另一个原因是,它 具有Unix的全部功能,任何使用Unix操作系统或想要学习 Unix操作系统的人都可以从Linux中获益.
Linux的出现绝不仅仅是为用户带来了一种价廉物美 的产品,使他们多了一种选择,其在更深层次上的意 义是,将给传统的软件版权制度,软件开发模式及企 业经营模式带来革命性的影响.我们已经习惯于花费 高昂费用买来的软件产品却不得不忍受其中的bug, 所有能做的只是抱怨和等待,现存的版权制度实际上 更大程度上是牺牲了广大用户的利益而保护了少数大 公司的利益.Linux的开放源码使用户拥有了知情权 和参与权,更符合用户的希望和需求,将成为软件业 未来的发展方向. 另一方面,Linux是中国软件业摆脱目前低水平的二 次开发,快速,健康发展的难得机遇.从以往的经 验教训来看,没有自主版权的操作系统就要受制于 人,整个软件业就好像踩在棉花团上,不可能获得 良好的自主发展的空间.Linux给我们提供了这样一 个大好时机,我们应当抓住它.
Linux程序设计基础—C环境(gcc gdb makefile)
博创科技 嵌入互动
Linux程序需要首先转化为低级机器语言即所谓的二进制代码 以后,才能被操作系统执行。 例如编程时,先用普通的编程语言生成一系列指令,这些 指令可被翻译为适当的可执行应用程序的二进制代码。这 个翻译过程可由解释器一步步来完成,或者也可以立即由 编译器明确地完成。 shell编程语言如BASH、TCSH、GAWK、Perl、Tcl和Tk都利 用自己的解释器。用这些语言编制的程序尽管是应用程序文 件,但可以直接运行。编译器则不同,它将生成一个独立的 二进制代码文件然后才可以运行。
© 2006 博创科技
博创科技 嵌入互动
GNU风格 (2/2)
当一个if中嵌套了另一个if-else时,应用花括号把if-else括起来。 要在同一个声明中同时说明结构标识和变量或者结构标识和类型定义 (typedef)。先定义变量,再使用。 尽量避免在if的条件中进行赋值。 请在名字中使用下划线以分割单词,尽量使用小写;把大写字母留给宏和 枚举常量,以及根据统一惯例使用的前缀。例如,应该使用类似 ignore_space_change_flag的名字;不要使用类似iCantReadThis的名字。 用于表明一个命令行选项是否给出的变量应该在选项含义的说明之后,而 不是选项字符之后被命名。
博创科技 嵌入互动
命令模式
4、复制和移动 yy 复制当前行到内存缓冲区 nyy 复制 n 行内容到内存缓冲区 y与光标移动的组合 p 将缓冲区的内容粘贴到光标的后面 P 将缓冲区的内容粘贴到光标的前面 另:在末行模式下实现移动 :n1,n2 m n3 : 把 n1到n2 行内容搬到第 n3 行后
© 2006 博创科技
© 2006 博创科技
博创科技 嵌入互动
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
CodingStyle/Linux内核代码风格这是一个简短的文档,描述了linux内核的首选代码风格。
代码风格是因人而异的,而且我不愿意把我的观点强加给任何人,不过这里所讲述的是我必须要维护的代码所遵守的风格,并且我也希望绝大多数其他代码也能遵守这个风格。
请在写代码时至少考虑一下本文所述的风格。
首先,我建议你打印一份GNU代码规范,然后不要读它。
烧了它,这是一个具有重大象征性意义的动作。
不管怎样,现在我们开始:第一章:缩进制表符是8个字符,所以缩进也是8个字符。
有些异端运动试图将缩进变为4(乃至2)个字符深,这几乎相当于尝试将圆周率的值定义为3。
理由:缩进的全部意义就在于清楚的定义一个控制块起止于何处。
尤其是当你盯着你的屏幕连续看了20小时之后,你将会发现大一点的缩进会使你更容易分辨缩进。
现在,有些人会抱怨8个字符的缩进会使代码向右边移动的太远,在80个字符的终端屏幕上就很难读这样的代码。
这个问题的答案是,如果你需要3级以上的缩进,不管用何种方式你的代码已经有问题了,应该修正你的程序。
简而言之,8个字符的缩进可以让代码更容易阅读,还有一个好处是当你的函数嵌套太深的时候可以给你警告。
留心这个警告。
在switch语句中消除多级缩进的首选的方式是让“switch”和从属于它的“case”标签对齐于同一列,而不要“两次缩进”“case”标签。
比如:switch (suffix) {case 'G':case 'g':mem <<= 30;break;case 'M':case 'm':mem <<= 20;break;case 'K':case 'k':mem <<= 10;/* fall through */default:break;}不要把多个语句放在一行里,除非你有什么东西要隐藏:if (condition) do_this;do_something_everytime;也不要在一行里放多个赋值语句。
内核代码风格超级简单。
就是避免可能导致别人误读的表达式。
除了注释、文档和Kconfig之外,不要使用空格来缩进,前面的例子是例外,是有意为之。
选用一个好的编辑器,不要在行尾留空格。
第二章:把长的行和字符串打散代码风格的意义就在于使用平常使用的工具来维持代码的可读性和可维护性。
每一行的长度的限制是80列,我们强烈建议您遵守这个惯例。
长于80列的语句要打散成有意义的片段。
每个片段要明显短于原来的语句,而且放置的位置也明显的靠右。
同样的规则也适用于有很长参数列表的函数头。
长字符串也要打散成较短的字符串。
唯一的例外是超过80列可以大幅度提高可读性并且不会隐藏信息的情况。
void fun(int a, int b, int c){if (condition)printk(KERN_W ARNING "Warning this is a long printk with ""3 parameters a: %u b: %u ""c: %u \n", a, b, c);elsenext_statement;}第三章:大括号和空格的放置C语言风格中另外一个常见问题是大括号的放置。
和缩进大小不同,选择或弃用某种放置策略并没有多少技术上的原因,不过首选的方式,就像Kernighan和Ritchie展示给我们的,是把起始大括号放在行尾,而把结束大括号放在行首,所以:if (x is true) {we do y}这适用于所有的非函数语句块(if、switch、for、while、do)。
比如:switch (action) {case KOBJ_ADD:return "add";case KOBJ_REMOVE:return "remove";case KOBJ_CHANGE:return "change";default:return NULL;}不过,有一个例外,那就是函数:函数的起始大括号放置于下一行的开头,所以:int function(int x){body of function}全世界的异端可能会抱怨这个不一致性是……呃……不一致的,不过所有思维健全的人都知道(a)K&R是_正确的_,并且(b)K&R是正确的。
此外,不管怎样函数都是特殊的(在C语言中,函数是不能嵌套的)。
注意结束大括号独自占据一行,除非它后面跟着同一个语句的剩余部分,也就是do语句中的“while”或者if语句中的“else”,像这样:do {body of do-loop} while (condition);和if (x == y) {..} else if (x > y) {...} else {....}理由:K&R。
也请注意这种大括号的放置方式也能使空(或者差不多空的)行的数量最小化,同时不失可读性。
因此,由于你的屏幕上的新行是不可再生资源(想想25行的终端屏幕),你将会有更多的空行来放置注释。
当只有一个单独的语句的时候,不用加不必要的大括号。
if (condition)action();这点不适用于本身为某个条件语句的一个分支的单独语句。
这时需要在两个分支里都使用大括号。
if (condition) {do_this();do_that();} else {otherwise();}3.1:空格Linux内核的空格使用方式(主要)取决于它是用于函数还是关键字。
(大多数)关键字后要加一个空格。
值得注意的例外是sizeof、typeof、alignof和__attribute__,这些关键字某些程度上看起来更像函数(它们在Linux里也常常伴随小括号而使用,尽管在C语言里这样的小括号不是必需的,就像“struct fileinfo info”声明过后的“sizeof info”)。
所以在这些关键字之后放一个空格:if, switch, case, for, do, while但是不要在sizeof、typeof、alignof或者__attribute__这些关键字之后放空格。
例如,s = sizeof(struct file);不要在小括号里的表达式两侧加空格。
这是一个反例:s = sizeof( struct file );当声明指针类型或者返回指针类型的函数时,“*”的首选使用方式是使之靠近变量名或者函数名,而不是靠近类型名。
例子:char *linux_banner;unsigned long long memparse(char *ptr, char **retptr);char *match_strdup(substring_t *s);在大多数二元和三元操作符两侧使用一个空格,例如下面所有这些操作符:= + - < > * / % | & ^ <= >= == != ? :但是一元操作符后不要加空格:& * + - ~ ! sizeof typeof alignof __attribute__ defined后缀自加和自减一元操作符前不加空格:++ --前缀自加和自减一元操作符后不加空格:++ --“.”和“->”结构体成员操作符前后不加空格。
不要在行尾留空白。
有些可以自动缩进的编辑器会在新行的行首加入适量的空白,然后你就可以直接在那一行输入代码。
不过假如你最后没有在那一行输入代码,有些编辑器就不会移除已经加入的空白,就像你故意留下一个只有空白的行。
包含行尾空白的行就这样产生了。
当git发现补丁包含了行尾空白的时候会警告你,并且可以应你的要求去掉行尾空白;不过如果你是正在打一系列补丁,这样做会导致后面的补丁失败,因为你改变了补丁的上下文。
第四章:命名C是一个简朴的语言,你的命名也应该这样。
和Modula-2和Pascal程序员不同,C程序员不使用类似ThisVariableIsATemporaryCounter这样华丽的名字。
C程序员会称那个变量为“tmp”,这样写起来会更容易,而且至少不会令其难于理解。
不过,虽然混用大小写的名字是不提倡使用的,但是全局变量还是需要一个具描述性的名字。
称一个全局函数为“foo”是一个难以饶恕的错误。
全局变量(只有当你真正需要它们的时候再用它)需要有一个具描述性的名字,就像全局函数。
如果你有一个可以计算活动用户数量的函数,你应该叫它“count_active_users()”或者类似的名字,你不应该叫它“cntuser()”。
在函数名中包含函数类型(所谓的匈牙利命名法)是脑子出了问题——编译器知道那些类型而且能够检查那些类型,这样做只能把程序员弄糊涂了。
难怪微软总是制造出有问题的程序。
本地变量名应该简短,而且能够表达相关的含义。
如果你有一些随机的整数型的循环计数器,它应该被称为“i”。
叫它“loop_counter”并无益处,如果它没有被误解的可能的话。
类似的,“tmp”可以用来称呼任意类型的临时变量。
如果你怕混淆了你的本地变量名,你就遇到另一个问题了,叫做函数增长荷尔蒙失衡综合症。
请看第六章(函数)。
第五章:Typedef不要使用类似“vps_t”之类的东西。
对结构体和指针使用typedef是一个错误。
当你在代码里看到:vps_t a;这代表什么意思呢?相反,如果是这样struct virtual_container *a;你就知道“a”是什么了。
很多人认为typedef“能提高可读性”。
实际不是这样的。
它们只在下列情况下有用:(a) 完全不透明的对象(这种情况下要主动使用typedef来隐藏这个对象实际上是什么)。
例如:“pte_t”等不透明对象,你只能用合适的访问函数来访问它们。
注意!不透明性和“访问函数”本身是不好的。
我们使用pte_t等类型的原因在于真的是完全没有任何共用的可访问信息。
(b) 清楚的整数类型,如此,这层抽象就可以帮助消除到底是“int”还是“long”的混淆。
u8/u16/u32是完全没有问题的typedef,不过它们更符合类别(d)而不是这里。
再次注意!要这样做,必须事出有因。
如果某个变量是“unsigned long“,那么没有必要typedef unsigned long myflags_t;不过如果有一个明确的原因,比如它在某种情况下可能会是一个“unsigned int”而在其他情况下可能为“unsigned long”,那么就不要犹豫,请务必使用typedef。
(c) 当你使用sparse按字面的创建一个新类型来做类型检查的时候。