Chinaunix首页 | 论坛 | 博客
  • 博客访问: 48832
  • 博文数量: 18
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 12
  • 用 户 组: 普通用户
  • 注册时间: 2018-04-03 10:12
文章分类
文章存档

2018年(18)

我的朋友

分类: LINUX

2018-07-26 10:47:36

概述:
    通过Makefile传递宏参数进行挑拣编译,是编程中常用的技术。
    Windows我不会,也不想会。这里只谈 Linux/GNU系统。
    在Linux平台下,编程大体分为两种,内核态编程和用户空间编程。对于内核态编程,对于大多数人而言,
都是采用内核模块的方式,将自己的代码加入到内核之中。用户空间的编程就多种多样了。
    但是无论是在那种context下编程,我们使用的基本上都是GNU的工具:Make,Gcc,LD等。而且无论代码要在那种context运行,都需要经过预处理,编译,连接,代码优化等过程。在这个过程之中,这里讨论的只适用于预处理阶段,也就是说选择性的进行编译。
    由于在内核态,通过kernel module的方式进行编译的时候,程序员主要是借助于Linux kernel KBuild编译系统;然而,在用户空间编程的时候,所有的工作都需要我们自己来作,所以两者之间存在不同。

一. 用户空间
     因为实际上进行预处理的只是Gcc工具,而make工具只是一个解决依赖关系的工具。所以问题就简化成如何通过make向gcc传递参数。
     通过简单的例子来说明:
hello.c
  1. #include

  2. void main(void) {
  3. #ifdef DEBUG
  4.      printf("you ask for debug!\n");
  5. #endif
  6.      printf("we must say goodbye\n");
  7.      return;
  8. }
Makefile:
  1. ifeq ($(DEBUG),y)
  2. CFLAGS := $(CFLAGS) -DDEBUG
  3. endif

  4. hello: hello.c
  5. $(CC) $(CFLAGS) $< -o $@
执行过程:
  1. [ville@localhost test]$ ls
  2. hello.c Makefile
  3. [ville@localhost test]$ make
  4. cc hello.c -o hello
  5. [ville@localhost test]$ ./hello
  6. we must say goodbye
  7. [ville@localhost test]$ rm hello
  8. [ville@localhost test]$ ls
  9. hello.c Makefile
  10. [ville@localhost test]$ make DEBUG:=y
  11. cc -DDEBUG hello.c -o hello
  12. [ville@localhost test]$ ./hello
  13. you ask for debug!
  14. we must say goodbye
  15. [ville@localhost test]$
通过以上的简单例子说明如何通过宏开关进行条件编译。

二. 在内核空间的module形式
    KBuild是Linux Kernel的编译系统,但是最终实际执行编译连接的还是GNU GCC LD。虽然我们是程序员,但是在KBuild的问题上,我们已经成为了软件的使用者。对于用户而言,我们应当更多关注功能,会使用是最终目的,当然如果有时间学习一下KBuild也是十分有意义的!
    有问题,看文档!Linux Kernel一向以文档不全不规范而闻名世界,但是这个KBuild的文档还是有的,
  1. linuxXXXXX/Documentation/kbuild 目录下:

  2. 00-INDEX
  3. kbuild.txt
  4. kconfig-language.txt
  5. kconfig.txt
  6. makefiles.txt
  7. modules.txt
有空还是要看看的!!!
      在makefile.txt 第284行,---3.7 Complilation Flags一节中有说明。
     以前都是使用EXTRA_XFLAGS,现在还是支持,但是建议使用xxflags-y这些内置变量了。
    ccflags-y:$(CC)的编译选项添加这里,宏开关也在这里添加
    asflags-y:as汇编器使用的
    ldflags-y :ld链接器使用的

还是用一个例子来演示:

ville.c :
  1. /**
  2. * Author : ville lee villelee1987@gmail.com
  3. * Create Time : 2010/07/31
  4. * Description : This module implements a virtual file system.
  5. * Aimming at learning the theory of Linux VFS.
  6. *
  7. * Change Log :
  8. * version author Date Log
  9. *
  10. *
  11. *
  12. * */

  13. #include
  14. #include
  15. #include



  16. /**
  17. * init function of the module
  18. *
  19. * */
  20. static int __init
  21. ville_init(void)
  22. {
  23. #ifdef DEBUG
  24.      /* we give the debug message like: module name : function name : debug message */
  25.      printk(KERN_ALERT "ville :ville_init: you ask for debug!\n");
  26. #endif
  27.      printk(KERN_ALERT "ville :ville_init: ville module init!\n");
  28.      return 0;
  29. }

  30. static void __exit
  31. ville_exit(void)
  32. {
  33. #ifdef DEBUG
  34.      /* we give the debug message like: module name : function name : debug message */
  35.      printk(KERN_ALERT "ville :ville_exit: you ask for debug!\n");
  36. #endif
  37.      printk(KERN_ALERT "ville :ville_exit: ville module exit!\n");

  38.      return;
  39. }

  40. module_init(ville_init);
  41. module_exit(ville_exit);

  42. MODULE_LICENSE("GPL");
  43. MODULE_AUTHOR("ville lee");

Makefile:
  1. ## if module is built in the kernel module
  2. ## system. Give the work to kbuild.

  3. # provide the default value to module name and ccflags-y
  4. ifeq ($(MODULE),)
  5.      MODULE := ville
  6. endif
  7. ifeq ($(DEBUG),y)
  8.      ccflags-y += -DDEBUG
  9. endif


  10. ifneq ($(KERNELRELEASE),)
  11.      obj-m := $(MODULE).o
  12. else
  13.      KERNELDIR := /lib/modules/$(shell uname -r)/build
  14.      PWD := $(shell pwd)

  15. default:
  16.      $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
  17. endif

  18. .PHONY:clean
  19. clean:
  20.      echo "cleaning ...."
  21.      rm modules.order Module.symvers \
  22.         $(MODULE).ko $(MODULE).mod.c \
  23.         $(MODULE).mod.o $(MODULE).o
  24.      echo "clean up"

操作:
 



  1. [ville@localhost source]$ ls
  2. Makefile ville.c ville.h
  3. [ville@localhost source]$ make
  4. make -C /lib/modules/2.6.35.13-91.fc14.i686.PAE/build M=/home/ville/Programming/VFS/villefs/source modules
  5. make[1]: Entering directory `/usr/src/kernels/2.6.35.13-91.fc14.i686.PAE'
  6. CC [M] /home/ville/Programming/VFS/villefs/source/ville.o
  7. Building modules, stage 2.
  8. MODPOST 1 modules
  9. CC /home/ville/Programming/VFS/villefs/source/ville.mod.o
  10. LD [M] /home/ville/Programming/VFS/villefs/source/ville.ko
  11. make[1]: Leaving directory `/usr/src/kernels/2.6.35.13-91.fc14.i686.PAE'
  12. [ville@localhost source]$ su
  13. Password:
  14. [root@localhost source]# insmod ville.ko
  15. [root@localhost source]# tail /var/log/messages
  16. Aug 1 21:52:20 localhost kernel: [ 527.943854] ville :ville_init: ville module init!
  17. [root@localhost source]# rmmod ville
  18. [root@localhost source]# tail /var/log/messages
  19. Aug 1 21:52:20 localhost kernel: [ 527.943854] ville :ville_init: ville module init!
  20. Aug 1 21:55:06 localhost kernel: [ 694.160046] ville :ville_exit: ville module exit!
  21. [root@localhost source]# exit
  22. exit
  23. [ville@localhost source]$ ls
  24. Makefile modules.order Module.symvers ville.c ville.h ville.ko ville.mod.c ville.mod.o ville.o
  25. [ville@localhost source]$ make clean
  26. echo "cleaning ...."
  27. cleaning ....
  28. rm modules.order Module.symvers \
  29. ville.ko ville.mod.c \
  30. ville.mod.o ville.o
  31. echo "clean up"
  32. clean up
  33. [ville@localhost source]$ make DEBUG:=y
  34. make -C /lib/modules/2.6.35.13-91.fc14.i686.PAE/build M=/home/ville/Programming/VFS/villefs/source modules
  35. make[1]: Entering directory `/usr/src/kernels/2.6.35.13-91.fc14.i686.PAE'
  36. CC [M] /home/ville/Programming/VFS/villefs/source/ville.o
  37. Building modules, stage 2.
  38. MODPOST 1 modules
  39. CC /home/ville/Programming/VFS/villefs/source/ville.mod.o
  40. LD [M] /home/ville/Programming/VFS/villefs/source/ville.ko
  41. make[1]: Leaving directory `/usr/src/kernels/2.6.35.13-91.fc14.i686.PAE'

  42. [ville@localhost source]$ ls
  43. Makefile modules.order Module.symvers ville.c ville.h ville.ko ville.mod.c ville.mod.o ville.o
  44. [ville@localhost source]$ su
  45. Password:
  46. [root@localhost source]# insmod ville.ko
  47. [root@localhost source]# tail /var/log/messages
  48. Aug 1 21:44:24 localhost rtkit-daemon[1721]: Successfully made thread 1838 of process 1836 (/usr/bin/pulseaudio) owned by '500' RT at priority 5.
  49. Aug 1 21:44:24 localhost rtkit-daemon[1721]: Successfully made thread 1839 of process 1836 (/usr/bin/pulseaudio) owned by '500' RT at priority 5.
  50. Aug 1 21:44:24 localhost pulseaudio[1836]: bluetooth-util.c: Error from ListAdapters reply: org.freedesktop.DBus.Error.Spawn.ChildExited
  51. Aug 1 21:44:26 localhost rtkit-daemon[1721]: Successfully made thread 1870 of process 1870 (/usr/bin/pulseaudio) owned by '500' high priority at nice level -11.
  52. Aug 1 21:44:26 localhost pulseaudio[1870]: pid.c: Daemon already running.
  53. Aug 1 21:44:41 localhost dbus: [system] Rejected send message, 2 matched rules; type="method_call", sender=":1.56" (uid=500 pid=1855 comm="nautilus) interface="org.freedesktop.DBus.Properties" member="GetAll" error name="(unset)" requested_reply=0 destination=":1.18" (uid=0 pid=1588 comm="/usr/sbin/console-kit-daemon))
  54. Aug 1 21:52:20 localhost kernel: [ 527.943854] ville :ville_init: ville module init!
  55. Aug 1 21:55:06 localhost kernel: [ 694.160046] ville :ville_exit: ville module exit!
  56. Aug 1 21:56:17 localhost kernel: [ 764.867120] ville :ville_init: you ask for debug!
  57. Aug 1 21:56:17 localhost kernel: [ 764.867127] ville :ville_init: ville module init!
  58. [root@localhost source]# rmmod ville
  59. [root@localhost source]# tail /var/log/messages
  60. Aug 1 21:44:24 localhost pulseaudio[1836]: bluetooth-util.c: Error from ListAdapters reply: org.freedesktop.DBus.Error.Spawn.ChildExited
  61. Aug 1 21:44:26 localhost rtkit-daemon[1721]: Successfully made thread 1870 of process 1870 (/usr/bin/pulseaudio) owned by '500' high priority at nice level -11.
  62. Aug 1 21:44:26 localhost pulseaudio[1870]: pid.c: Daemon already running.
  63. Aug 1 21:44:41 localhost dbus: [system] Rejected send message, 2 matched rules; type="method_call", sender=":1.56" (uid=500 pid=1855 comm="nautilus) interface="org.freedesktop.DBus.Properties" member="GetAll" error name="(unset)" requested_reply=0 destination=":1.18" (uid=0 pid=1588 comm="/usr/sbin/console-kit-daemon))
  64. Aug 1 21:52:20 localhost kernel: [ 527.943854] ville :ville_init: ville module init!
  65. Aug 1 21:55:06 localhost kernel: [ 694.160046] ville :ville_exit: ville module exit!
  66. Aug 1 21:56:17 localhost kernel: [ 764.867120] ville :ville_init: you ask for debug!
  67. Aug 1 21:56:17 localhost kernel: [ 764.867127] ville :ville_init: ville module init!
  68. Aug 1 21:56:44 localhost kernel: [ 792.003641] ville :ville_exit: you ask for debug!
  69. Aug 1 21:56:44 localhost kernel: [ 792.003648] ville :ville_exit: ville module exit!

总结:
      通过这两个例子,就了解了如何在用户空间和内核态模块中使用开关宏来进行条件编译。




   ville

阅读(1475) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~