首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
宝塔
V2EX  ›  程序员

一个实际工程中的 C 语言问题

  •  
  •   feng32 · 92 天前 · 1548 次点击
    这是一个创建于 92 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有一个 Linux 驱动模块,它会给每个设备分配一个数据结构

    struct A {
        ...
        struct list_head list;
        ...
    }
    

    这个数据结构内含一个 “带头节点的双向循环链表”,这个 struct list_head 是 Linux 内核中的一个标准结构

    struct list_head {
        struct list_head *prev;
        struct list_head *next;
    }
    

    一开始的时候,链表为空,只有一个头节点,所以 prev 指向自己,next 也指向自己

    当系统上有两个设备的时候,就会产生 2 个结构体 a1 和 a2,同时也会产生两条链表

    现在,出于一些原因,我需要让 a1 和 a2 共享一条链表。把 struct A 中的 struct list_head list 改为 struct list_head *list 这个方案看起来很直接,但是一旦这么改,代码中其它数百处引用这个 list 成员的地方,就需要一一修改了,成本很高。

    如果能让 list 变成类似 C++ 中的引用变量,似乎可以解决问题,但是 Linux Kernel 不支持 C++

    请问 C 语言里,是否还存在一些其它的可能性,可以避免更新所有引用 list 变量的代码?

    16 回复  |  直到 2019-08-16 07:48:41 +08:00
        1
    wutiantong   92 天前
    先分析清楚你的业务场景吧,不要一上来就一通乱改。
        2
    feng32   92 天前
    @wutiantong 我已经故意把业务场景隐去了,这里讨论的就是 C 语言的奇技淫巧
        3
    takemeh   92 天前
    每个设备对应的结构体里面的链表头是放什么数据的呢?
    另外膜拜写内核的大佬.
        4
    feng32   92 天前
    @takemeh 链表里装的数据是另一个 struct B,和这个问题没什么关系

    内核里的 list_head 和学校里学的传统链表不太一样,可以参考这篇文章:

    https://www.cnblogs.com/zhuyp1015/archive/2012/06/02/2532240.html
        5
    msg7086   92 天前
    你改成引用变量也要改签名吧,一样的。
        6
    cqcsdzmt   92 天前
    a1->list->prev=b1->list->prev;
    a1->list->next=b1->list->next;
    ....
        7
    cqcsdzmt   92 天前
    如上问题,骚 easy 的东西为什么想的这么复杂。
        8
    cqcsdzmt   92 天前
    更正一下
    a1.list->prev=b1->list->prev;
    a1.list->next=b1->list->next;
        9
    cqcsdzmt   92 天前   ♥ 1
    更正一下
    a1.list->prev=b1.list->prev;
    a1.list->next=b1.list->next;
        10
    feng32   92 天前
    @cqcsdzmt 如果没有对 head 取地址的操作,那么它就是对的,但是实际上在 linux kernel 的使用场景下,它是有问题的

    list_head 链表的遍历,就是不断 next 一直到达原先的 head,如果这么赋值,对 a1 的遍历就死循环了
        11
    feng32   92 天前
    @msg7086 如果大多数情况引用的是 struct A,函数签名里就没有 list 的类型了,所以这还是有很大作用的
        13
    menyakun   92 天前
    好像没办法不改吧,我怎么感觉这个 list 结构应该放在设备的 inode 中,然后在 open 的时候,`file->private_data->list = list`这样
        14
    secondwtq   92 天前
    ... 正解就是让电脑帮你去改

    用奇技淫巧只会留下更多坑
        15
    boywhp   92 天前
    全局定义一个 struct list_head xxList = {0};
        16
    waruqi   92 天前 via Android
    A 里面还是改成 *list 不过所有操作 list 的 api 你用宏做下替换,比如之前是 insert(&list, x) ,用法保持不变 你写个 insert 宏替换之前的 insert func

    #define insert_org insert
    #define insert(list, x) insert_org(*(list), x)
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2372 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 27ms · UTC 03:02 · PVG 11:02 · LAX 19:02 · JFK 22:02
    ♥ Do have faith in what you're doing.