zoukankan      html  css  js  c++  java
  • 利用 constructor 属性完成 module_init() 设计模式 Hello

    C/C++应用程序

    一、简介

    1. __attribute__语法格式为:__attribute__ (( attribute-list ))

    若函数被设定为 constructor 属性,则该函数会在 main() 函数执行之前被自动的执行。类似的,若函数被设定为 destructor 属性,则该函数会在 main() 函数执行之后或者 exit() 被调用后被自动的执行。

    2. 当存在多个 __attribute__((constructor)) 修饰的函数时,也不用持锁,因为是单线程执行的。

    3. 还可以使用 __attribute__((constructor(prio))) 指定优先级,从而决定调用次序,优先级prio取值范围是 0--65535,其中 0--100 是预留的,不能使用,优先级数值越小优先级越高,越优先被执行调用。只要指定了优先级,就算是指定的优先级是65535也还是会比没有指定优先级的先调用。

    二、 测试例子

    1. C程序

    #include<stdio.h>
    
    __attribute__((constructor)) void before_main()  
    {  
       printf("before main.\n");  
    }  
      
    __attribute__((destructor)) void after_main()  
    {  
       printf("after main.\n");  
    }  
      
    int main()  
    {  
       printf("in main.\n");  
       return 0;  
    }
    
    /*
    //执行结果:
    $ ./pp
    before main.
    in main.
    after main.
    */

    2. C++程序

    #include<iostream>
    
    using namespace std;
    
    
    __attribute__((constructor)) void before_main() // void 在前后都行
    {  
        //cout<<"Before Main"<<endl;  //注释掉就不 Segmentation fault 了。
        int i;
        i++;
    }
    
    __attribute__((destructor)) void after_main()  
    {  
        cout<<"After Main"<<endl;  
    }
    
    
    class AAA{  
    public:  
        AAA(){  
            cout<<"AAA construct"<<endl;  
        }     
        ~AAA(){  
            cout<<"AAA destructor" <<endl;  
        }     
    };
    
    AAA A; //全局类对象
    
    
    int main()  
    {  
        cout<<"in main"<<endl;  
        return 0;  
    }
    
    /*
    执行结果:
    $ ./pp
    AAA construct
    in main
    AAA destructor
    After Main
    */

    注:测试发现,C++中 __attribute__((constructor)) 修饰的函数中不能执行 cout<<"..."<<endl 语句,否则会 Segmentation fault


    三、实现类似Linux内核中 module_init() 的设计模式

    1. 实现

    Linux内核中 module_init() 是通过链接器脚本实现的,用户空间程序可以使用 constructor 属性实现。

    (1) core.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "core.h"
    
    struct function *g_functions[FUNC_NUM] = {NULL};
    
    static int module_init()
    {
        int i, ret = 0;
    
        for (i = 0; i < ARRAY_SIZE(g_functions); i++) {
            if (g_functions[i] && g_functions[i]->init) {
                ret = g_functions[i]->init();
            }
        }
    
        return ret;
    }
    
    static int module_exit()
    {
        int i;
    
        for (i = 0; i < ARRAY_SIZE(g_functions); i++) {
            if (g_functions[i] && g_functions[i]->release) {
                g_functions[i]->release();
                g_functions[i] = NULL;
            }
        }
    
        return 0;
    }
    
    static int module_do_function(int code)
    {
        int i, ret = 0;
    
        for (i = 0; i < ARRAY_SIZE(g_functions); i++) {
            if (g_functions[i] && g_functions[i]->id == code) {
                ret = g_functions[i]->execute(code);
            }
        }
    
        return ret;
    }
    
    
    int main(int argc, char *argv[])
    {
        int ret, code = 0;
    
        if (argc == 2) {
            code = atoi(argv[1]);
        }
    
        module_init();
        module_do_function(code);
        module_exit();
    }

    (2) core.h

    #define FUNC_NUM 16
    
    #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
    
    struct function {
        int id;
        int (*init)(void);
        int (*execute)(int code);
        void (*release)(void);
    };
    
    extern struct function *g_functions[FUNC_NUM];
    
    
    #define function_register(name)                                    \
    void __attribute__((constructor)) function_##name##_register(void) \
    {                                                                  \
        int i;                                                         \
        for (i = 0; i < ARRAY_SIZE(g_functions); i++) {                \
            if (!g_functions[i]) {                                     \
                g_functions[i] = &func_##name;                         \
                break;                                                 \
            }                                                          \
        }                                                              \
        printf("%s, id=%d.\n", __func__, func_##name.id);              \
    }

    (3) camera.c

    #include <stdio.h>
    #include "core.h"
    
    #define CAMERA_FUN_ID 1
    
    
    static int camera_init(void) {
        int ret = 0;
    
        printf("camera_init called.\n");
    
        return ret;
    }
    
    static int camera_execute(int code) {
        int ret = 0;
    
        printf("camera_execute called.\n");
    
        return ret;
    }
    
    static void camera_release(void) {
        printf("camera_release called.\n");
    }
    
    static struct function func_camera = {
        .id = CAMERA_FUN_ID,
        .init = camera_init,
        .execute = camera_execute,
        .release = camera_release,
    };
    
    function_register(camera);

    (4) led.c

    #include <stdio.h>
    #include "core.h"
    
    #define LED_FUN_ID 2
    
    
    static int led_init(void) {
        int ret = 0;
    
        printf("led_init called.\n");
    
        return ret;
    }
    
    static int led_execute(int code) {
        int ret = 0;
    
        printf("led_execute called.\n");
    
        return ret;
    }
    
    static void led_release(void) {
        printf("led_release called.\n");
    }
    
    static struct function func_led = {
        .id = LED_FUN_ID,
        .init = led_init,
        .execute = led_execute,
        .release = led_release,
    };
    
    function_register(led);

    2. 测试

    $ gcc *.c -o pp
    
    $ ./pp
    function_camera_register, id=1.
    function_led_register, id=2.
    camera_init called.
    led_init called.
    camera_release called.
    led_release called.
    
    $ ./pp 1
    function_camera_register, id=1.
    function_led_register, id=2.
    camera_init called.
    led_init called.
    camera_execute called.
    camera_release called.
    led_release called.

    3. 若需要再添加其它命令,值需要添加一个文件并注册即可,不用改原有文件。

  • 相关阅读:
    MySQL事务_transaction
    mysql
    反射跳过泛型检查
    spring java.io.FileNotFoundException cannot be opened because it does not exist
    Servlet中ServletConfig的作用
    Exception in thread "main" java.lang.ClassCastException: java.base/java.util.HashMap$Values cannot be cast to java.base/java.util.ArrayList
    java中字符串和其他数据类型之间使用“+”号连接
    comboBox加载数据
    自动填充
    3号随笔,搭建web环境
  • 原文地址:https://www.cnblogs.com/hellokitty2/p/15612442.html
Copyright © 2011-2022 走看看