Linux内核编码风格(译文)

合集下载

谈谈为 Linux 内核写驱动的编码规范

谈谈为 Linux 内核写驱动的编码规范

谈谈为 Linux 内核写驱动的编码规范最近在向Linux内核提交一些驱动程序,在提交的过程中,发现自己的代码离Linux内核的coding style要求还是差很多。

当初自己对内核文档里的CodingStyle一文只是粗略的浏览,真正写代码的时候在很多细节上会照顾不周。

不过,在不遵守规则的程序员队伍里,我并不是孤独的。

如果去看drivers/staging下的代码,就会发现很多驱动程序都没有严格遵守内核的coding style,而且在很多驱动程序的TODO文件里,都会把"checkpatch.pl fixes"作为自己的目标之一(checkpatch.pl是用来检查代码是否符合coding style的脚本)。

不可否认,coding style是仁者见仁、智者见智的事情。

比如Microsoft所推崇的匈牙利命名法,在Linus看来就是及其脑残(brain damaged)的做法。

也许您并不赞成Linus制定的coding style,但在提交内核驱动这件事上,最好还是以大局为重。

对于这么一个庞大的集市式的开发来说,随意书写代码必将带来严重的可维护性的灾难。

(题图来自:mota.ru)一些辅助工具当代码量达到一定程度时,手动去检查和修改coding style是非常繁琐的工作,幸好,我们还有一些工具可以使用。

scripts/checkpatch.pl这是一个检查代码是否符合内核编码规范的的脚本。

顾名思义,checkpatch是用来检查patch的,默认的调用也确实如此。

如果用来检查原文件,需要加上“-f”的选项。

我们来看一段无聊的代码(文件名为print_msg.c):1.void print_msg(int a)2.{3. switch (a) {4. case 1:5. printf("a == 1\n");6. break;7.8. case 2:9. printf("a == 2\n");10. break;11. }12.}这段代码的coding style是否有问题呢?用checkpatch.pl来检查一下:1.scripts/checkpatch.pl -f print_msg.c检查的结果是:1.ERROR: switch and case should be at the same indent2.#3: FILE: switch.c:3:3.+ switch (a) {4.+ case 1:5.[...]6.+ case 2:7.8.total: 1 errors, 0 warnings, 12 lines checked9.10.switch.c has style problems, please review. If any of theseerrors11.are false positives report them to the maintainer, see12.CHECKPATCH in MAINTAINERS.在Linux内核的coding style里,switch和case要求有相同的缩进。

Linux 内核编译配置选项简介

Linux 内核编译配置选项简介

General setup常规设置Local versio n - append to kernel release在内核版本后面加上自定义的版本字符串(小于64字符),可以用"uname -a"命令看到Automatically append version information to the versio n string 自动在版本字符串后面添加版本信息,编译时需要有perl以及git仓库支持Support for paging of anonymous memory (swap)使用交换分区或者交换文件来做为虚拟内存System V IPCSystem V进程间通信(IPC)支持,许多程序需要这个功能.必选,除非你知道自己在做什么POSIX Message QueuesPOSIX消息队列,这是POSIX IPC中的一部分BSD Process Accounting将进程的统计信息写入文件的用户级系统调用,主要包括进程的创建时间/创建者/内存占用等信息Export task/process statistics through netlink通过netlink接口向用户空间导出任务/进程的统计信息,与BSD ProcessAccounting的不同之处在于这些统计信息在整个任务/进程生存期都是可用的UTS NamespacesUTS名字空间支持,不确定可以不选Auditing support审计支持,某些内核模块(例如SELinux)需要它,只有同时选择其子项才能对系统调用进行审计Kernel .config support把内核的配置信息编译进内核中,以后可以通过scripts/extract-ikconfig脚本来提取这些信息Cpuset support只有含有大量CPU(大于16个)的SMP系统或NUMA(非一致内存访问)系统才需要它Kernel->user space relay support (formerly relayfs)在某些文件系统上(比如debugfs)提供从内核空间向用户空间传递大量数据的接口Initramfs source file(s)initrd已经被initramfs取代,如果你不明白这是什么意思,请保持空白Optimize for size (Look out for broken compilers!)编译时优化内核尺寸(使用"-Os"而不是"-O2"参数编译),有时会产生错误的二进制代码Enable extended accounting over taskstats收集额外的进程统计信息并通过taskstats接口发送到用户空间Configure standard kernel features (for small systems)配置标准的内核特性(为小型系统)Include all symbols in kallsyms在kallsyms中包含内核知道的所有符号,内核将会增大300KDo an extra kallsyms pass除非你在kallsyms中发现了bug并需要报告这个bug才打开该选项Loadable module support可加载模块支持Enable loadable module support打开可加载模块支持,如果打开它则必须通过"make modules_install"把内核模块安装在/lib/modules/中Module unloading允许卸载已经加载的模块Forced module unloading允许强制卸载正在使用中的模块(比较危险)Module versioning support允许使用其他内核版本的模块(可能会出问题)Source checksum for all modules为所有的模块校验源码,如果你不是自己编写内核模块就不需要它Block layer块设备层Enable the block layer块设备支持,使用硬盘/USB/SCSI设备者必选Support for Large Block Devices仅在使用大于2TB的块设备时需要Support for tracing block io actions块队列IO跟踪支持,它允许用户查看在一个块设备队列上发生的所有事件,可以通过blktrace程序获得磁盘当前的详细统计数据Support for Large Single Files仅在可能使用大于2TB的文件时需要IO SchedulersIO调度器Anticipatory I/O scheduler假设一个块设备只有一个物理查找磁头(例如一个单独的SATA硬盘),将多个随机的小写入流合并成一个大写入流,用写入延时换取最大的写入吞吐量.适用于大多数环境,特别是写入较多的环境(比如文件服务器)Deadline I/O scheduler使用轮询的调度器,简洁小巧,提供了最小的读取延迟和尚佳的吞吐量,特别适合于读取较多的环境(比如数据库)CFQ I/O scheduler使用QoS策略为所有任务分配等量的带宽,避免进程被饿死并实现了较低的延迟,可以认为是上述两种调度器的折中.适用于有大量进程的多用户系统Default I/O scheduler默认IO调度器Processor type and features中央处理器(CPU)类型及特性Symmetric multi-processing support对称多处理器支持,如果你有多个CPU或者使用的是多核CPU就选上.此时"Enhanced Real Time Clock Support"选项必须开启,"Advanced PowerManagement"选项必须关闭Subarchitecture Type处理器的子架构,大多数人都应当选择"PC-compatible"Processor family处理器系列,请按照你实际使用的CPU选择Generic x86 support通用x86支持,如果你的CPU能够在上述"Processor family"中找到就别选HPET Timer SupportHPET是替代8254芯片的新一代定时器,i686及以上级别的主板都支持,可以安全的选上Maximum number of CPUs支持的最大CPU数,每增加一个内核将增加8K体积SMT (Hyperthreading) scheduler support支持Intel的超线程(HT)技术Multi-core scheduler support针对多核CPU进行调度策略优化Preemption Model内核抢占模式No Forced Preemption (Server)适合服务器环境的禁止内核抢占Voluntary Kernel Preemption (Desktop)适合普通桌面环境的自愿内核抢占Preemptible Kernel (Low-Latency Desktop)适合运行实时程序的主动内核抢占Preempt The Big Kernel Lock可以抢占大内核锁,应用于实时要求高的场合,不适合服务器环境Machine Check Exception让CPU检测到系统故障时通知内核,以便内核采取相应的措施(如过热关机等) Check for non-fatal errors on AMD Athlon/Duron / IntelPentium 4每5秒检测一次这些cpu的非致命错误并纠正它们,同时记入日志check for P4 thermal throttling interrupt当P4的cpu过热时显示一条警告消息Enable VM86 support虚拟X86支持,在DOSEMU下运行16-bit程序或XFree86通过BIOS初始化某些显卡的时候才需要Toshiba Laptop supportToshiba笔记本模块支持Dell laptop supportDell笔记本模块支持Enable X86 board specific fixups for reboot修正某些旧x86主板的重起bug,这种主板基本绝种了/dev/cpu/microcode - Intel IA32 CPU microcode support使用不随Linux内核发行的IA32微代码,你必需有IA32微代码二进制文件,仅对Intel的CPU有效/dev/cpu/*/msr - Model-specific register support在多cpu系统中让特权CPU访问x86的MSR寄存器/dev/cpu/*/cpuid - CPU informatio n support能从/dev/cpu/x/cpuid获得CPU的唯一标识符(CPUID)Firmware Drivers固件驱动程序BIOS Enhanced Disk Drive calls determine boot disk 有些BIOS支持从某块特定的硬盘启动(如果BIOS不支持则可能无法启动),目前大多数BIOS还不支持BIOS update support for DELL systems via sysfs 仅适用于DELL机器Dell Systems Management Base Driver仅适用于DELL机器High Memory Support最高内存支持,总内存小于等于1G的选"off",大于4G的选"64G"Memory split如果你不是绝对清楚自己在做什么,不要改动这个选项Memory model一般选"Flat Memory",其他选项涉及内存热插拔64 bit Memory and IO resources使用64位的内存和IO资源Allocate 3rd-level pagetables from highmem在内存很多(大于4G)的机器上将用户空间的页表放到高位内存区,以节约宝贵的低端内存Math emulation数学协处理器仿真,486DX以上的cpu就不要选它了MTRR (Memory Type Range Register) support打开它可以提升PCI/AGP总线上的显卡2倍以上的速度,并且可以修正某些BIOS错误Boot from EFI supportEFI是一种可代替传统BIOS的技术(目前的Grub/LILO尚不能识别它),但是现在远未普及Enable kernel irq balancing让内核将irq中断平均分配给多个CPU以进行负载均衡,但是要配合irqbanlance守护进程才行Use register arguments使用"-mregparm=3"参数编译内核,将前3个参数以寄存器方式进行参数调用,可以生成更紧凑和高效的代码Enable seccomp to safely compute untrusted bytecode只有嵌入式系统可以不选Timer frequency内核时钟频率,桌面推荐"1000 HZ",服务器推荐"100 HZ"或"250 HZ"kexec system call提供kexec系统调用,可以不必重启而切换到另一个内核kernel crash dumps被kexec启动后产生内核崩溃转储Physical address where the kernel is loaded内核加载的物理地址,除非你知道自己在做什么,否则不要修改.在提供kexec系统调用的情况下可能要修改它Support for hot-pluggable CPUs对热插拔CPU提供支持Compat VDSO support如果Glibc版本大于等于2.3.3就不选,否则就选上Power management options电源管理选项Power Management support电源管理有APM和ACPI两种标准且不能同时使用.即使关闭该选项,X86上运行的Linux也会在空闲时发出HLT指令将CPU进入睡眠状态Legacy Power Management API传统的电源管理API,比如软关机和系统休眠等接口Power Management Debug Support仅供调试使用Driver model /sys/devices/.../power/state files 内核帮助文档反对使用该选项,即将被废除ACPI (Advanced Configuration and Power Interface) Support必须运行acpid守护程序ACPI才能起作用.ACPI是为了取代APM而设计的,因此应该尽量使用ACPI而不是APMAC Adapter如果你的系统可以在AC和电池之间转换就可以选Battery通过/proc/acpi/battery向用户提供电池状态信息,用电池的笔记本可以选Button守护程序捕获Power,Sleep,Lid按钮事件,并根据/proc/acpi/event做相应的动作,软件控制的poweroff需要它Video仅对集成在主板上的显卡提供ACPI2.0支持,且不是所有集成显卡都支持Generic Hotkey统一的热键驱动,建议不选Fan允许通过用户层的程序来对系统风扇进行控制(开,关,查询状态),支持它的硬件并不多Dock支持由ACPI控制的集线器(docking stations)Processor让ACPI处理空闲状态,并使用ACPI C2和C3处理器状态在空闲时节省电能,同时它还被cpufreq的"Performance-state drivers"选项所依赖Thermal Zone系统温度过高时可以利用ACPI thermal zone及时调整工作状态以避免你的CPU被烧毁ASUS/Medio n Laptop Extras ASUS笔记本专用,以提供额外按钮的支持,用户可以通过/proc/acpi/asus来打开或者关闭LCD的背光/调整亮度/定制LED的闪烁指示等功能IBM ThinkPad Laptop Extras IBM ThinkPad专用Toshiba Laptop Extras Toshiba笔记本专用Disable ACPI for systemsbefore Jan 1st this year 输入四位数的年份,在该年的1月1日前不使用ACPI的功能("0"表示一直使用)Debug Statements 详细的ACPI调试信息,不搞开发就别选Power ManagementTimer Support 这个Timer在所有ACPI兼容的平台上都可用,且不会受PM功能的影响,建议总是启用它.如果你在kernel log中看到了'many lost ticks'那就必须启用它ACPI0004,PNP0A05and PNP0A06Container Driver 支持内存和CPU的热插拔Smart BatterySystem 支持依赖于I2C的"智能电池".这种电池非常老旧且罕见,还与当前的ACPI标准兼容性差APM (Advanced Power Management) BIOS SupportAPM在SMP机器上必须关闭,一般来说当前的笔记本都支持ACPI,所以应尽量关闭该该选项Ignore USER SUSPEND只有NEC Versa M系列的笔记本才需要选择这一项Enable PM at boot time系统启动时即启用APM,选上这个选项能让系统自动的进行电源管理,但常常导致启动时死机Make CPU Idle calls when idle系统空闲时调用空闲指令(halt),只有老式的CPU才需要选它,且对于SMP系统必须关闭Enable console blanking using APM在屏幕空白时关闭LCD背光,事实上对所有的笔记本都无效RTC stores time in GMT将硬件时钟应该设为格林威治时间,否则视为本地时间.建议你使用GMT,这样你无须为时区的改变而担心Allow interrupts during APM BIOS calls 允许APM的BIOS调用时中断,IBM Thinkpad的一些新机器需要这项.如果休眠时挂机(包括睡下去就醒不来),可以试试它Use real mode APM BIOS call to power off 此驱动为某些有Bug的BIOS准备,如果你的系统不能正常关机或关机时崩溃,可以试试它CPU Frequency scaling允许动态改变CPU主频,达到省电和降温的目的,必须同时启用下面的一种governor才行Enable CPUfreq debugging允许对CPUfreq进行调试CPU frequency translation statistics通过sysfs文件系统输出CPU频率变换的统计信息CPU frequency translation statistics details输出详细的CPU频率变换统计信息Default CPUFreq governor默认的CPU频率调节器'performance' governor'性能'优先,静态的将频率设置为cpu支持的最高频率'powersave' governor'节能'优先,静态的将频率设置为cpu支持的最低频率'userspace' governor for userspace frequencyscaling既允许手动调整cpu频率,也允许用户空间的程序动态的调整cpu频率(需要额外的调频软件,比如cpufreqd)'ondemand' cpufreq policy governor '立即响应',周期性的考察CPU负载并自动的动态调整cpu频率(不需要额外的调频软件),适合台式机'conservative' cpufreq governor '保守',和'ondemand'相似,但是频率的升降是渐变式的(幅度不会很大),更适合用于笔记本/PDA/AMD64环境ACPI Processor P-States driver 将ACPI2.0的处理器性能状态报告给CPUFreq processor drivers以决定如何调整频率,该选项依赖于ACPI->Processor{省略的部分请按照自己实际使用的CPU选择}/proc/acpi/processor/../performance interface内核帮助文档反对使用该选项,即将被废除Relaxed speedstep capabilitychecks放松对系统的speedstep兼容性检查,仅在某些老旧的Intel系统上需要打开Bus options (PCI, PCMCIA, EISA, MCA, ISA)总线选项PCI supportPCI支持,如果使用了PCI或PCI Express设备就必选PCI access modePCI访问模式,强列建议选"Any"(系统将优先使用"MMConfig",然后使用"BIOS",最后使用"Direct"检测PCI设备)PCI Express supportPCI Express支持(目前主要用于显卡和千兆网卡)PCI Express Hotplug driver如果你的主板和设备都支持PCI Express热插拔就可以选上Use po lling mechanism for hot-plug events对热插拔事件采用轮询机制,仅用于测试目的Root Port Advanced Error Reporting support由PCI Express AER驱动程序处理发送到Root Port的错误信息Message Signaled Interrupts (MSI and MSI-X) PCI Express支持两类中断:INTx使用传统的IRQ中断,可以与现行的PCI总线的驱动程序和操作系统兼容;MSI则是通过inbound Memory Write触发和发送中断,更适合多CPU系统.可以使用"pci=nomsi"内核引导参数关闭MSIPCI Debugging将PCI调试信息输出到系统日志里Interrupts on hypertransport devices允许本地的hypertransport设备使用中断ISA support现在基本上没有ISA的设备了,如果你有就选吧MCA support微通道总线,老旧的IBM的台式机和笔记本上可能会有这种总线NatSemi SCx200 support在使用AMD Geode处理器的机器上才可能有PCCARD (PCMCIA/CardBus) supportPCMCIA卡(主要用于笔记本)支持Enable PCCARD debugging仅供调试16-bit PCMCIA support一些老的PCMCIA卡使用16位的CardBus32-bit CardBus support当前的PCMCIA卡基本上都是32位的CardBusCardBus yenta-compatible bridge support使用PCMCIA卡的基本上都需要选择这一项,子项请按照自己实际使用的PCMCIA卡选择{省略的部分请按照自己实际使用的PCMCIA卡选择} PCI Hotplug SupportPCI热插拔支持,如果你有这样的设备就到子项中去选吧Executable file formats可执行文件格式Kernel support for ELF binariesELF是开放平台下最常用的二进制文件格式,支持动态连接,支持不同的硬件平台.除非你知道自己在做什么,否则必选Kernel support for a.out and ECOFF binaries早期UNIX系统的可执行文件格式,目前已经被ELF格式取代Kernel support for MISC binaries允许插入二进制的封装层到内核中,使用Java,.NET,Python,Lisp等语言编写的程序时需要它Networking网络Networking options网络选项Network packet debugging在调试不合格的包时加上额外的附加信息,但在遇到Dos攻击时你可能会被日志淹没Packet socket这种Socket可以让应用程序(比如tcpdump,iptables)直接与网络设备通讯,而不通过内核中的其它中介协议Packet socket: mmapped IO让Packet socket驱动程序使用IO映射机制以使连接速度更快Unix domain sockets一种仅运行于本机上的效率高于TCP/IP的Socket,简称Unix socket.许多程序都使用它在操作系统内部进行进程间通信(IPC),比如X Window和syslogTransformatio n user configuratio n interface为IPsec(可在ip层加密)之类的工具提供XFRM用户配置接口支持Transformatio n sub po licy supportXFRM子策略支持,仅供开发者使用PF_KEY sockets用于可信任的密钥管理程序和操作系统内核内部的密钥管理进行通信,IPsec依赖于它TCP/IP networkingTCP/IP协议当然要选IP: multicasting群组广播,似乎与网格计算有关,仅在使用MBONE的时候才需要IP: advanced router高级路由,如果想做一个路由器就选吧IP: policy routing策略路由IP: equal cost multipath用于路由的基于目的地址的负载均衡IP: verbose route monitoring显示冗余的路由监控信息IP: kernel level autoconfiguratio n在内核启动时自动配置ip地址/路由表等,需要从网络启动的无盘工作站才需要这个东西IP: tunnelingIP隧道,将一个IP报文封装在另一个IP报文内的技术IP: GRE tunnels over IP基于IP的GRE(通用路由封装)隧道IP: multicast routing多重传播路由IP: ARP daemon support这东西尚处于试验阶段就已经被废弃了IP: TCP syncookie support抵抗SYN flood攻击的好东西,要启用它必须同时启用/proc文件系统和"Sysctl support",然后在系统启动并挂载了/proc之后执行"echo1 >/proc/sys/net/ipv4/tcp_syncookies"命令IP: AH transformatio nIPsec验证头(AH)实现了数据发送方的验证处理,可确保数据既对于未经验证的站点不可用也不能在路由过程中更改IP: ESP transformationIPsec封闭安全负载(ESP)实现了发送方的验证处理和数据加密处理,用以确保数据不会被拦截/查看或复制IP: IPComp transformationIPComp(IP静荷载压缩协议),用于支持IPsecIP: IPsec transport modeIPsec传输模式,常用于对等通信,用以提供内网安全.数据包经过了加密但IP头没有加密,因此任何标准设备或软件都可查看和使用IP头IP: IPsec tunnel modeIPsec隧道模式,用于提供外网安全(包括虚拟专用网络).整个数据包(数据头和负载)都已经过加密处理且分配有新的ESP头/IP头和验证尾,从而能够隐藏受保护站点的拓扑结构IP: IPsec BEET modeIPsec BEET模式INET: socket monitoring interfacesocket监视接口,一些Linux本地工具(如:包含ss的iproute2)需要使用它TCP: advanced congestio n control高级拥塞控制,如果没有特殊需求(比如无线网络)就别选了,内核会自动将默认的拥塞控制设为"Cubic"并将"Reno"作为候补IP: Virtual Server ConfigurationIP虚拟服务器允许你基于多台物理机器构建一台高性能的虚拟服务器,不玩集群就别选了The IPv6 protocol你要是需要IPv6就选吧NetLabel subsystem supportNetLabel子系统为诸如CIPSO与RIPSO之类能够在分组信息上添加标签的协议提供支持,如果你看不懂就别选了Security Marking对网络包进行安全标记,类似于nfmark,但主要是为安全目的而设计,如果你不明白的话就别选Network packet filtering (replaces ipchains)Netfilter可以对数据包进行过滤和修改,可以作为防火墙("packet filter"或"proxy-based")或网关(NAT)或代理(proxy)或网桥使用.选中此选项后必须将"Fast switching"关闭,否则将前功尽弃Network packet filtering debugging仅供开发者调试Netfilter使用Bridged IP/ARP packets filtering如果你希望使用一个针对桥接的防火墙就打开它Core Netfilter Configuration核心Netfilter配置(当包流过Chain时如果match某个规则那么将由该规则的target来处理,否则将由同一个Chain中的下一个规则进行匹配,若不match所有规则那么最终将由该Chain的policy进行处理)Netfilter netlink interface允许Netfilter在与用户空间通信时使用新的netlink接口.netlink Socket是Linux用户态与内核态交流的主要方法之一,且越来越被重视.Netfilter NFQUEUE over NFNETLINK interface通过NFNETLINK接口对包进行排队Netfilter LOG over NFNETLINK interface通过NFNETLINK接口对包记录.该选项废弃了ipt_ULOG和ebg_ulog机制,并打算在将来废弃基于syslog的ipt_LOG和ip6t_LOG模块Layer 3 Independent Connection tracking独立于第三层的链接跟踪,通过广义化的ip_conntrack支持其它非IP协议的第三层协议Netfilter Xtables support如果你打算使用ip_tables,ip6_tables,arp_tables之一就必须选上"CLASSIFY" target support允许为包设置优先级,一些排队规则(atm,cbq,dsmark,pfifo_fast,htb,prio)需要使用它"CONNMARK" target support类似于"MARK",但影响的是连接标记的值"DSCP" target support允许对ip包头部的DSCP(Differentiated Services Codepoint)字段进行修改,该字段常用于Qos"MARK" target support允许对包进行标记(通常配合ip命令使用),这样就可以改变路由策略或者被其它子系统用来改变其行为"NFQUEUE" target Support用于替代老旧的QUEUE(iptables内建的target之一),因为NFQUEUE能支持最多65535个队列,而QUEUE只能支持一个"NOTRACK" target support允许规则指定哪些包不进入链接跟踪/NAT子系统"SECMARK" target support允许对包进行安全标记,用于安全子系统"CONNSECMARK" target support针对链接进行安全标记,同时还会将连接上的标记还原到包上(如果链接中的包尚未进行安全标记),通常与SECMARK target联合使用"comment" match support允许你在iptables规则集中加入注释"connbytes" per-connection counter match support允许针对单个连接内部每个方向(进/出)匹配已经传送的字节数/包数"connmark" connection mark match support允许针对每个会话匹配先前由"CONNMARK"设置的标记值"conntrack" connection tracking match support连接跟踪匹配,是"state"的超集,它允许额外的链接跟踪信息,在需要设置一些复杂的规则(比如网关)时很有用"DCCP" protocol match supportDCCP是打算取代UDP的新传输协议,它在UDP的基础上增加了流控和拥塞控制机制,面向实时业务"DSCP" match support允许对IP包头的DSCP字段进行匹配"ESP" match support允许对IPSec包中的ESP头进行匹配,使用IPsec的话就选上吧"helper" match support加载特定协议的连接跟踪辅助模块,由该模块过滤所跟踪的连接类型的包,比如ip_conntrack_ftp模块"length" match support允许对包的长度进行匹配"limit" match support允许根据包的进出速率进行规则匹配,常和"LOG target"配合使用以抵抗某些Dos攻击"mac" address match support允许根据以太网的MAC进行匹配,常用于无线网络环境"mark" match support允许对先前由"MARK"标记的特定标记值进行匹配IPsec "policy" match support使用IPsec就选上吧Multiple port match support允许对TCP或UDP包同时匹配多个端口(通常情况下只能匹配一个端口)"physdev" match support允许对到达的或将要离开的物理桥端口进行匹配"pkttype" packet type match support允许对封包目的地址类别(广播/群播/直播)进行匹配"quota" match support允许对总字节数的限额值进行匹配"realm" match support允许对iptables中的路由子系统中的realm值进行匹配"sctp" protocol match support流控制传输协议(SCTP),十年以后也许能够普及的东西"state" match support这是对包进行分类的有力工具,它允许利用连接跟踪信息对连接中处于特定状态的包进行匹配"statistic" match support允许根据一个给定的百分率对包进行周期性的或随机性的匹配"string" match support允许根据包所承载的数据中包含的特定字符串进行匹配"tcpmss" match support允许根据TCP SYN包头中的MSS(最大分段长度)选项的值进行匹配IP: Netfilter Configuration针对IPv4的Netfilter配置Connection tracking (required for masq/NAT)链接跟踪.可用于报文伪装或地址转换,也可用于增强包过滤能力Connection tracking flow accounting允许针对每个连接记录已经传送的字节/包数,常用于connbytes matchConnection mark tracking support允许对连接进行标记,与针对单独的包进行标记的不同之处在于它是针对连接流的.CONNMARK target和connmark match需要它的支持Connection tracking security mark support允许对连接进行安全标记,通常这些标记包(SECMARK)复制到其所属连接(CONNSECMARK),再从连接复制到其关联的包(SECMARK)Connection tracking events连接跟踪事件支持.如果启用这个选项,连接跟踪代码将提供一个notifier链,它可以被其它内核代码用来获知连接跟踪状态的改变Connection tracking netlink interface支持基于netlink的用户空间接口SCTP protocol connection tracking supportSCTP是IP网面向多媒体通信的新一代的流控制传输协议FTP protocol supportFTP协议IRC protocol supportIRC协议是一种用来实时聊天协议,用过mIRC的人应当不陌生NetBIOS name service protocol supportNetBIOS名字服务协议TFTP protocol supportTFTP是基于UDP的比FTP简单的文件传输协议Amanda backup protocol supportAmanda备份协议PPTP protocol support点对点隧道协议(PPTP)是一种支持多协议虚拟专用网络的网络技术,ADSL用户对它应该很熟悉H.323 protocol supportITU-T提出的用于IP电话的协议SIP protocol supportIETE提出的用于IP电话的协议IP Userspace queueing via NETLINK已废弃IP tables support (required for filtering/masq/NAT)要用iptables就肯定要选上IP range match support允许对ip地址的范围进行匹配TOS match support允许对ip包头的TOS(Type Of Service)字段进行匹配recent match support可以创建一个或多个刚刚使用过的ip地址列表,然后根据这些列表进行匹配ECN match support允许对TCP/IP包头的ECN(Explicit Congestion Notification)字段进行匹配.ECN是一种显式拥塞通知技术,它不但要求路由器支持而且要求端到端主机的支持,其基本思想是当路由器发生早期拥塞时不是丢弃包而是尽量对包进行标记,接收方接到带有ECN提示的包时,通知发送方网络即将发生拥塞,也就是它通过对包的标记提示TCP源即将发生拥塞,从而引发拥塞避免算法AH match support允许对IPSec包头的AH字段进行匹配TTL match support允许对ip包头的TTL(生存期)字段进行匹配Owner match support允许对本地生成的包按照其宿主(user,group,process,session)进行匹配address type match support允许对地址类型(单播,本地,广播)进行匹配hashlimit match support是limit的升级,它基于你选择的ip地址与/或端口动态的创建以limit为桶(bucket)的哈希表.它可以创建诸如"为每个特定的目标IP分配10kpps"或"允许每个特定的源IP分配500pps"之类的规则Packet filtering定义filter表以允许对包进行过滤REJECT target support允许返回一个ICMP错误而不是简单的丢弃包LOG target support允许将符合条件的包头信息通过syslog进行记录ULOG target support透过netlink socket将符合条件的封包交给用户空间的ulogd守护进程.反对使用该选项,因为它已经被NETFILTER_NETLINK_LOG代替TCPMSS target support允许修改TCP包头中的MSS(最大分段长度)选项值Full NAT允许进行伪装/端口转发以及其它的NAT功能,仅在你需要使用iptables中的nat 表时才需要选择Packet mangling在iptables中启用mangle表以便对包进行各种修改,常用于改变包的路由raw table support (required for NOTRACK/TRACE)在iptables中添加一个'raw'表,该表在netfilter框架中非常靠前,并在PREROUTING和OUTPUT链上有钩子,从而可以对收到的数据包在连接跟踪前进行处理ARP tables supportARP表支持.只有在局域网中才有ARP欺骗问题,另外路由器也会遭到ARP欺骗ARP packet filteringARP包过滤.对于进入和离开本地的ARP包定义一个filter表,在桥接的情况下还可以应用于被转发ARP包ARP payload mangling允许对ARP包的荷载部分进行修改,比如修改源和目标物理地址IPv6: Netfilter Configuration针对IPv6的Netfilter配置,需要的话可以参考前面IPv4的Netfilter配置进行选择DECnet: Netfilter Configuratio n针对DECnet的Netfilter配置Bridge: Netfilter Configuration针对桥接的Netfilter配置DCCP Configuratio n数据报拥塞控制协议在UDP的基础上增加了流控和拥塞控制机制,使数据报协议能够更好地用于流媒体业务的传输SCTP Configuration流控制传输协议是一种新兴的传输层协议.TCP协议一次只能连接一个IP地址而在SCTP协议一次可以连接多个IP地址且可以自动平衡网络负载,一旦某一个IP 地址失效会自动将网络负载转移到其他IP地址上TIPC Configuration透明内部进程间通信协议,以共享内存为基础实现任务和资源的调度,专门用于内部集群通信Asynchronous Transfer Mode (ATM)异步传输模式(ATM)支持802.1d Ethernet Bridging802.1d以太网桥802.1Q VLAN Support802.1Q虚拟局域网DECnet SupportDECnet是一种很生僻的协议ANSI/IEEE 802.2 LLC type 2 Support看不懂可以不选The IPX protocolIPX协议Appletalk protocol support与Mac机器通信的协议CCITT X.25 Packet Layer大约没人需要这东西LAPB Data Link Driver大约没人需要这东西。

Linux内核源代码解读

Linux内核源代码解读

最初,Linux核心的最开始部分是用8086汇编语言编写的。当开始运行时,核心将自己装入到绝对地址0x90000(576K; 1001,0000,0000,0000,0000),再将其后的2k字节装入到地址0x90200(576.5k; 1001,0000,0010,0000,0000)处,最后将核心的其余部分装入到0x10000(64k; 1,0000,0000,0000,0000).
mov cx,#256
sub si,si
| 寄存器清零
sub di,di
| 寄存器清零
rep
movw
mov bx,#0x0007
| page 0, attribute 7 (normal)
mov bp,#msg1
| 显示Loading System ...
mov ax,#0x1301
| 将由SI作为指针的源串中的一个字节或字或双字传送到由DI作为指针的目的串中,并根据标志DF值自动修
| 改这两个指针以指向串中下一项。若带有前缀REP,则重复执行这一传送,直到CX寄存器等于零为止。
| 源地址:DS=0x07C0(31K;0111,1100,0000,0000);
| 目的地址:ES=0x9000(576K;1001,0000,0000,0000,0000)
提问者: Linux探索者 - 一级
答复 共 1 条
检举
系统初始化程序 boot.s 的分析 [转]
系统初始化程序 boot.s 的分析:
阚志刚,2000/03/20下午,在前人的基础之上进行整理完善
**********************************************************************************************

linux 的编码格式

linux 的编码格式

linux 的编码格式**Linux 编码格式简介**在Linux 系统中,编码格式起着至关重要的作用。

它是一种将字符转换为二进制的方式,以便在计算机内部进行存储和传输。

了解Linux 编码格式对于更好地使用这个强大的操作系统至关重要。

**Linux 常用编码格式对比**Linux 系统中存在多种编码格式,其中最常用的有ASCII、UTF-8、GBK 等。

1.ASCII:这是一种最基本的编码格式,主要应用于英文和数字。

然而,它在处理中文等复杂字符时存在局限性。

2.UTF-8:这是一种广泛应用于Linux 的编码格式,它可以表示几乎所有的Unicode 字符。

UTF-8 具有良好的兼容性和跨平台性,是目前Linux 系统中最为推荐的编码格式。

3.GBK:这是一种针对中文设计的编码格式,适用于简体中文环境。

在Linux 系统中,GBK 编码可以满足大部分中文文本的处理需求。

**如何选择合适的编码格式**在选择编码格式时,需要考虑以下几个方面:1.目标用户:根据您的读者群体,选择他们熟悉的编码格式。

例如,面向国内用户,可以选择GBK 编码;面向国际用户,可以选择UTF-8 编码。

2.文件兼容性:确保所选编码格式与其他操作系统和软件的兼容性。

例如,使用UTF-8 编码可以确保在各种操作系统和设备上都能正常显示文本。

3.存储空间:较小的编码格式如ASCII 和GBK 占用存储空间较少,但处理字符范围有限;UTF-8 编码虽然兼容性较好,但占用存储空间相对较大。

4.文本处理需求:根据您的文本处理需求,选择合适的编码格式。

例如,如果您需要处理大量特殊字符或Unicode 字符,可以选择UTF-8 编码。

**编码格式在Linux 中的应用场景**编码格式在Linux 系统中有着广泛的应用场景,如:1.文本编辑器:不同的编码格式可以在文本编辑器中显示和编辑不同类型的文本。

2.编程语言:编程语言中的变量名、注释和字符串常使用编码格式进行存储和处理。

linux内核编译 menuconfig详解

linux内核编译 menuconfig详解

内核版本 2.6.32[*]Prompt for development and/or incomplete code/drivers显示尚在开发中或尚未完成的代码与驱动.你应该选择它,因为有许多设备可能必需选择这个选项才能进行配置,实际上它是安全的。

这个选项同样会让一些老的驱动的可用。

如果你选了Y,你将会得到更多的阿尔法版本的驱动和代码的配置菜单。

()Local version - append to kernel release在内核版本后面加上自定义的版本字符串(小于64字符),可以用"uname -a"命令看到[ ]Automatically append version information to the version string自动生成版本信息。

这个选项会自动探测你的内核并且生成相应的版本,使之不会和原先的重复。

这需要Perl的支持。

由于在编译的命令make-kpkg 中我们会加入- –append-to-version 选项来生成自定义版本,所以这里选N。

Kernel compression mode (Gzip)内核压缩模式选baip2gzip用于UNIX系统的文件压缩。

后缀为.gz的文件。

现今已经成为Internet 上使用非常普遍的一种数据压缩格式,或者说一种文件格式。

HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术。

大流量的WEB站点常常使用GZIP压缩技术来让用户感受更快的速度。

bzip2是一个基于Burrows-Wheeler 变换的无损压缩软件,压缩效果比传统的LZ77/LZ78压缩算法来得好。

它是一款免费软件。

bzip2能够进行高质量的数据压缩。

它利用先进的压缩技术,能够把普通的数据文件压缩10%至15%,压缩的速度和解压的效率都非常高!支持现在大多数压缩格式,包括tar、gzip 等等。

lzma是一个Deflate和LZ77算法改良和优化后的压缩算法,开发者是Igor Pavlov,2001年被首次应用于7-Zip压缩工具中,是 2001年以来得到发展的一个数据压缩算法。

Linux内核编译说明

Linux内核编译说明

Linux内核编译说明1.Linux内核源码结构:内核源码中主要包含以下子目录:arch :包含了与体系结构相关的代码对应于每一个支持的体系结构,有一个相应的子目录如i386、arm、alpha等。

其每个体系结构子目录下包含几个主要的子目录:kernel :包含与体系结构相关的内核代码mm :包含与体系结构相关的内存管理代码lib :包含与体系结构相关的库代码documentation:包含内核的文档drivers :包含设备驱动代码。

每类设备有相应的子目录,如char 、block、net等fs :包含文件系统的代码。

每个支持的文件系统有相应的子目录,如ext2、proc等include :内核头文件,对每一种体系结构,分别有相应的子目录。

init :包含内核初始化代码lib :包含内核的库代码mm :包含内存管理代码kernel :包含内核管理代码net :包含网络部分的代码2.系统引导的过程在pc机上系统启动过程:系统加电以后bois对系统完成监测设置后将控制权交给硬盘上MBR中的BootLoader 在这里即是lilo或grub等。

BootLoader 将操作系统代码调入内存,然后将控制权交给arch/i386/boot中的Setup.S 这段程序。

Setup.S 这段程序在386实模式下对系统进行基本的检测和设置后转入保护模式把控制权交给Head.SHead.S 建立内存管理和中断管理的框架后调用init/main.c中的start_kernel()函数在start_kernel执行完成后用户就可以登录和使用linux了。

Start_kernel()函数在init/main.c 中定义。

Start_kernel的流程中的主要步骤:setup_arch(&command_line); 用于和处理器、内存等最基本的硬件相关部分的初始化。

在arch/i386/kernel/setup.c 中定义;parse_options(command_line); 把启动时得到的参数从命令行的字符串中分离出来并赋给相应的变量。

linux 的编码格式

linux 的编码格式

linux 的编码格式Linux的编码格式简介:Linux是一种开源操作系统,广泛应用于各个领域。

在Linux系统中,编码格式是一个关键的概念,它决定了如何表示和存储文本数据。

本文将介绍常见的Linux编码格式及其特点,以及在使用Linux系统时应该注意的问题。

一、ASCII编码ASCII(American Standard Code for Information Interchange)是最早的字符编码标准,在计算机中使用7位二进制数来表示字符。

它定义了128个字符,包括大写和小写字母、数字以及一些常见的符号,如英文标点符号和控制字符。

由于ASCII编码只能表示有限的字符集合,不能满足国际化需求,因此逐渐被更全面的编码格式所取代。

二、UTF-8编码UTF-8(Unicode Transformation Format-8bit)是一种可变长度的Unicode编码标准,支持全球范围内的字符集。

UTF-8编码在Linux系统中被广泛使用,因为它能够兼容ASCII编码。

UTF-8使用1至4个字节来表示一个字符,具备良好的兼容性和可扩展性。

它可以表示几乎所有的字符,包括汉字、拉丁字母、希腊字母等。

UTF-8编码是Linux系统默认的字符编码格式。

三、GBK编码GBK编码是中国国家标准的字符集,它是对GB2312编码的扩充,能够覆盖更多的中文字符。

GBK编码使用2个字节表示一个字符,其中包含了21003个汉字和符号以及部分非汉字字符。

在Linux系统中,如果需要处理中文字符的文本数据,可以选择使用GBK编码来存储和表示。

四、其他编码格式除了ASCII、UTF-8和GBK编码外,Linux还支持其他一些编码格式,如UTF-16、ISO-8859等。

这些编码格式通常用于特定的情况和需求,比如在处理特定语言或特定文件格式时使用。

五、在Linux系统中选择编码格式的注意事项1. 考虑文本数据的应用场景和需求。

Linux内核编程规范与代码风格

Linux内核编程规范与代码风格

Linux内核编程规范与代码风格这是⼀篇阐述Linux内核编程代码风格的⽂档,译者以学习为⽬的进⾏翻译。

1 缩进Tab的宽度是⼋个字符,因此缩进的宽度也是⼋个字符。

有些异教徒想让缩进变成四个字符,甚⾄是两个字符的宽度,这些⼈和那些把 PI 定义为 3 的⼈是⼀个路⼦的。

注意:缩进的全部意义在于清晰地定义语句块的开始与结束,特别是当你盯着屏幕20个⼩时之后,你会发现长的缩进宽度的作⽤。

现在有些⼈说⼋个字符的宽度太宽了,这会让代码往右移很远,在⼀块⼋⼗字符宽的屏幕上,这样的代码会很难阅读。

对此的回答是,如果你写的代码需要超过三层的缩进,那么你把⼀切都搞砸了,你应该修复你的程序。

简⽽⾔之,⼋个字符宽度的缩进让代码更容易阅读,并且额外的好处就是提醒你,不要在⼀个函数⾥写太多层的嵌套逻辑。

请记住这个警⽰。

switch语句的缩进⽅式是让case与switch对齐: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中,永远不要使⽤空格作为缩进,上⾯的例⼦是故意犯的错误。

找⼀个像样的编辑器,不要在⾏末留有空格。

2 换⾏规范代码风格的⽬的是提⾼代码的可读性和维护性。

单⾏的宽度限制为⼋⼗列,这是强烈推荐的设置。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
பைடு நூலகம்
(c) when you use sparse to literally create a _new_ type for type-checking. (d) 在某种特殊情况下,和标准 C99 类型相同的类型。 虽然让眼睛和头脑来适应类似“uint32_t”一样的标准类型几乎不需要花时间,可还是 有些人拒绝接受。 因此, “u8/u16/u32/u64”类型和它们的有符号类型,可以说是 Linux 的事实标准,是可 以使用的,但并不做强制要求。 在修改代码时,如果该代码中已经选择了某个类型集,那么应该遵循现有规则。 (e) 可以在用户空间安全使用的类型。 在某些用户空间可见的结构体里, 我们不能要求 C99 类型, 并且不能用上面提到的 “u32” 类型。因此,我们在和用户空间共享的所有结构体中使用__u32 或者是类似的类型。 可能还有其他情况也会用到 typedef,不过基本的规则是永远不要使用 typedef,除非可 以明确的应用上述规则中的一个。 第六节:函数 函数应该短小精悍,并且只实现一个功能。它们应该一屏或者两屏显示完(我们都知道 ISO/ANSI 屏幕大小是 80x24) ,只实现一个功能,并把它做好。 一个函数的最大长度是和该函数的复杂度和缩进级数成反比的。 所以, 如果你有这样一 个函数:只有一个 switch 语句,但有很多个不同的 case 分支,每个分支里面只需要做很小 的事情。这样的函数尽管很长,但也是可以接受的。 不过, 如果你有一个复杂的函数, 而且你怀疑一个天分不是很高的高中一年级学生甚至 可能搞不清楚这个函数的功能,你应该更严格的遵守最大限制。 进行函数拆分,并为之取个具有描述性的名字(如果你觉得其对性能要求严格的话,你 可以要求编译器将它们内联展开,它往往会比你更好的完成任务。 ) 函数另外一个衡量标准是局部变量的数量。通常来说,不应超过 5-10 个,否则这个函 数就有问题了。需要重新考虑一下,把它分拆成更小的函数。这是为什么呢?人的大脑一般 可以轻松的同时跟踪 7 个不同的事物,如果再多的话,就会糊涂了。即便你聪颖过人,也可 能会记不清你 2 个星期前做过的事情。 在源文件里,使用空行隔开不同的函数。如果该函数需要被导出,它的 EXPORT*宏应 该紧贴在它的结束大括号之下。比如: int system_is_up(void) { return system_state == SYSTEM_RUNNING; } EXPORT_SYMBOL(system_is_up); 在函数原型中,包含函数名和它们的数据类型。虽然 C 语言里没有这样的要求,但在 Linux 里这是首选的做法,因为这样可以很简单的给读者提供更多的有价值的信息。 第七节 集中函数出口
最好也不要把多个赋值语句放在同一行。 内核代码应该是非常非常简单的!请避免使用过于巧妙的表达式^^ 除了注释、文档和 Kconfig 之外,最好不要使用空格来缩进,前面的例子就是一个反面 典型^^ 选择一个合适的编辑器,并且不要在行尾留空格! 第二节 适当的换行 代码风格的意义在于, 即使采用不同的编辑器, 仍然可以保证代码的可读性和可维护性。 每一行长度的限制是八十列,并且强烈建议应该是首选的。 长度超过八十列的语句可以分成几个有意义的片段,每个片段要明显短于原来的语句, 并且放的位置也要明显的靠右。 这个规则对于有很长参数列表的函数同也同样适用。 长字符 串也要打散成较短的字符串。 只有一种情况, 即超过八十列可以大幅度提高可读性并且不会 隐藏信息的情况,可以例外^^ void fun(int a, int b, int c) { if (condition) printk(KERN_WARNING "Warning this is a long printk with " "3 parameters a: %u b: %u " "c: %u \n", a, b, c); else next_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 } 全世界的异端可能会抱怨这个自相矛盾的规则,呃。 。 。确实是自相矛盾,不过所有思想 健全的人都知道,K&R 是正确的,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 里也常常伴随小括号使用, 尽管这类小括号不是必需的, 就像 “struct fileinfo info” 声明过后的“sizeof info” ) 。 所以下面这几个关键字之后要放一个空格: if, switch, case, for, do, while 但是 sizeof、typeof、alignof 或者__attribute__这些关键字后面,就不要放了。例如, s = sizeof(struct file); 不要在小括号内的表达式两侧加空格。这是一个反例: s = sizeof( struct file );
C 语言是一门朴素的语言,那么命名也应该如此。和 Modula-2 和 Pascal 程序员不一样, C 程序员不会使用类似 ThisVariableIsATemporaryCounter 这样酷毕的名字,而仅用“tmp”就 可以了,这样写起来更容易,也不会另其难以理解。 尽管如此, 给全局变量定义一个一目了然的名字还是必须的。 如果谁把全局变量定义成 “foo” ,应该拉出去毙了^^ 全局变量需要一个一目了然的名字, 全局函数也是这样。 如果你有一个用来统计活动用 户数量的函数,你应该命名为“ count_active_users() ”或者是类似的名字,而不应该叫 "cntusr()"。 在函数名中包含函数类型的做法(所谓的匈牙利命名法)应该是脑子坏掉了-无论如何 编译器是知道那些数据类型,并且能够进行类型检查,这样做只会困扰程序员。难怪微软的 程序满是 BUG^^ 局部变量应该言简意赅。如果需要定义一个变量来表示循环记数器,它应该被命名为 “i” 。命名为“loop_counter”是没什么好处的,如果它没有被误解的话。同理,只要是临 时的变量,不管什么类型都可以定义为“tmp” 。 可如果你怕混淆了本地变量名,你就遇到了另一个问题,叫做函数-增长-荷尔蒙-失衡综合症。请看第六节(函数) 。 第五节:Typedef 请不要定义类似“vps_t”之类的类型。 使用 typedef 来定义结构和指针的别名是错误的,当你看见代码里面有这样一句, vps_t a; “a”是什么呢? 反过来,如果代码这样写, struct virtual_container *a; 你就能知道"a"是什么了。 许多人认为 typedef 能帮助提高程序可读性,但事实确不是这样的。它们只在下列情况 下有用: (a) 完全不透明的对象(这种情况要主动隐藏这个对象的实际意义) 。例如: “pte_t”等 不透明对象,你只能用合适的访问函数来访问它们。注意!不透明性和“访问函数本身”是 不好的。我们使用 pte_t 等类型的原因在于确实是完全没有任何共用的可访问信息。 (b) 定义清晰的整数类型,这样就可以帮助我们避免把"int"和"long"混淆。u8/u16/u32 是完美的 typedef,不过它们更符合(d)中所言,而不是这里。再次注意!必须要出师有名! 如果某个变量是“unsigned long“,那么没有必要这样做, typedef unsigned long myflags_t; 不过如果有一个明确的原因,比如它在某种情况下可能会是一个“unsigned int”而在其 他情况下可能为“unsigned long” ,那么请不要犹豫,务必使用 typedef。
但是一元操作符后不要加空格: & * + ~ ! sizeof typeof alignof __attribute__ defined
相关文档
最新文档