一个实际工程中的 C 语言问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术题时复制粘贴 AI 生成的内容
feng32
V2EX    程序员

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

  •  
  •   feng32 2019-08-15 16:42:23 +08:00 2662 次点击
    这是一个创建于 2303 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

    #define insert_org insert
    #define insert(list, x) insert_org(*(list), x)
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2412 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 15:52 PVG 23:52 LAX 07:52 JFK 10:52
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86