
前12节课主要分析Linux内核中GNU C扩展的一些常见C语言语法. GNU C的这些扩展语法主要用于改善C语言标准和编译优化. 通过C标准的开发过程,我们还发现,对于某些编译器扩展的某些功能,或其他编程语言(例如: C ++)中的良好功能和语法,C标准也将及时吸收作为新的C语言标准.
在GNU C的这些扩展语法中,__attribute__和宏定义是两个主要功能. 在嵌入式低级系统中,尤其是Linux内核和U-boot,GNU C扩展的__attribute__属性被广泛用于辅助某些低级机制的实现或实现某些编译优化. 在宏定义方面嵌入式c语言课后习题 linux,我们可以通过语句表达式和可变参数宏的特性来定义功能复杂,安全可靠的高质量宏.
本教程中描述的某些功能是在工作或阅读Linux内核驱动程序源代码时经常遇到的一些功能. 掌握了这些扩展功能的使用之后,将来我会遇到类似的“好奇C语言”程序. 我知道该怎么分析. 此外,GNU C还具有其他一些扩展功能. 由于它们在内核中使用不多,或者只是做了一些编译优化,即使您不知道,由于空间限制,它也不会影响我们对代码的理解. 因此,我暂时不会谈论它,例如以下特征.
如果将来遇到类似的扩展名,则可以访问以下网站.
这里有一些C语言练习问题,您可以做一个. 查看您是否掌握了本教程. 如有任何疑问,可以通过阅读者圈与我讨论或加入QQ组(475504428).

1. 以下程序在不同的编译环境(例如C-Free嵌入式c语言课后习题 linux,VC ++ 6.0和TurboC)下编译并运行. 结果是否相等,为什么?
#include<stdio.h>
int main(void)
{
printf(size: %d\n, sizeof(int);
return 0;
}
2. 定义一个宏并找到两个数字中的最小值.
3. 将以下程序编译为可执行文件a.out,该文件可以在ARM平台上运行,然后反汇编该文件以查看变量global_val的地址.
int global_val = 10;
int uninit_val;
int main(void)
{
int local_val = 20;
return 0;
}

4. 在一个项目中,有两个源文件,如下所示,分析以下程序的运行结果.
//func.c
int a = 10;
int b;
int c __attribute__((weak)) = 30;
//main.c
int a;
int b = 20;
int c = 40;
int main(void)
{
printf(a: %d\n,a);
printf(b: %d\n,b);
printf(c: %d\n,c);
return 0;
}
5. 定义变量参数功能以实现级别打印控制: ERROR,DEBUG,INFO. 使用这三个宏分别代表级别打印. 例如,当定义ERROR时,仅打印错误信息;否则,仅显示错误信息. 定义DEBUG时,将打印错误和调试信息;定义INFO后,将打印所有打印信息.
6. 定义一个变量参数宏以实现级别打印控制: ERROR,DEBUG,INFO. 使用这三个宏来表示级别打印,例如,在定义ERROR宏时,仅打印错误信息. 在定义调试时,将打印错误和调试信息;定义INFO时,将打印所有打印信息.
7. 以下是Linux内核(Linux 4.4.0)中的一些宏定义,请分析它们实现的功能.

#define pr_emerg(fmt, ...) \
printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
#define pr_alert(fmt, ...) \
printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
#define pr_crit(fmt, ...) \
printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
#define pr_err(fmt, ...) \
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
#define pr_warning(fmt, ...) \
printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
#define pr_warn pr_warning
#define pr_notice(fmt, ...) \
printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
#define pr_info(fmt, ...) \
printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
8. 在Linux内核启动过程中,启动日志的末尾通常会有这样的信息.
Freeing unused kernel memory: 468K
请在本课程中使用section属性声明来分析此日志后面的内核初始化和内存释放过程.
9. 在嵌入式Linux驱动程序开发中,驱动程序模块不具有main()入口功能. 请使用从本课程中学到的知识来分析: 驱动程序如何运行和初始化.

10. 驱动程序分析: 在linux4.4源代码linux-4.4 / arch / arm / mach-footbridge / ebsa285.c中,分析以下代码的含义以及container_of宏的作用.
MACHINE_START(EBSA285, EBSA285)
/* Maintainer: Russell King */
.atag_offset = 0x100,
.video_start = 0x000a0000,
.video_end = 0x000bffff,
.map_io = footbridge_map_io,
.init_early = footbridge_sched_clock,
.init_irq = footbridge_init_irq,
.init_time = footbridge_timer_init,
.restart = footbridge_restart,
MACHINE_END
static void ebsa285_led_set(struct \
led_classdev *cdev, enum led_brightness b)
{
struct ebsa285_led *led = container_of(cdev,
struct ebsa285_led, cdev);
if (b == LED_OFF)
hw_led_state |= led->mask;
else
hw_led_state &= ~led->mask;
writeb(hw_led_state, xbus);
}
static enum led_brightness \
ebsa285_led_get(struct led_classdev *cdev)
{
struct ebsa285_led *led = container_of(cdev,
struct ebsa285_led, cdev);
return hw_led_state & led->mask ? LED_OFF : LED_FULL;
}
微信公众号: armlinuxfun
嵌入式视频教程: wanglitao.taobao.com
电子书下载地址: pan.baidu.com/s/1a6L0cyIQKKLlmIfRw7U6Dg
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-218868-1.html
口头抗议是解决不了什么问题嘀
只能用一次