Linux内核:为什么'子'结构把基础类信息在结束了吗? [英] Linux kernel: why do 'subclass' structs put base class info at end?

查看:112
本文介绍了Linux内核:为什么'子'结构把基础类信息在结束了吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在读的Linux内核美丽code 中的一章,作者讨论如何Linux的内核实现在C语言继承(除其他主题)。简单地说,一个基地结构的定义,为了从它继承了'子'结构在子类结构定义的结尾放置底座的的副本。笔者随后花了几页解释巧妙而复杂的宏观找出多少字节,以便从对象到对象的子部分的底座部分转换为备份。

I was reading the chapter in Beautiful Code on the Linux kernel and the author discusses how Linux kernel implements inheritance in the C language (amongst other topics). In a nutshell, a 'base' struct is defined and in order to inherit from it the 'subclass' struct places a copy of the base at the end of the subclass struct definition. The author then spends a couple pages explaining a clever and complicated macro to figure out how many bytes to back in order to convert from the base part of the object to the subclass part of the object.

我的问题:在子类的结构,为什么不申报的基础结构作为结构中的第一个的东西,而不是的最后的事?

My question: Within the subclass struct, why not declare the base struct as the first thing in the struct, instead of the last thing?

把基础结构的东西第一次的主要优势从基地到子类铸件的时候你就不需要在所有移动指针 - 从本质上讲,做演员只是意味着告诉编译器,让你的code使用的子结构安置了东西后额外的字段,该基地定义。

The main advantage of putting the base struct stuff first is when casting from the base to the subclass you wouldn't need to move the pointer at all - essentially, doing the cast just means telling the compiler to let your code use the 'extra' fields that the subclass struct has placed after the stuff that the base defines.

只是为了澄清我的问题有点让我扔些code OUT:

Just to clarify my question a little bit let me throw some code out:

struct device { // this is the 'base class' struct
     int a;
     int b;
     //etc
}
struct usb_device { // this is the 'subclass' struct
    int usb_a;
    int usb_b;
    struct device dev; // This is what confuses me - 
                       // why put this here, rather than before usb_a?
}

如果发生对象有一个指针开发领域的USB_DEVICE对象的内部则为了将它转换回一个人需要从该指针减去8的USB_DEVICE对象。但是,如果开发是在一个USB_DEVICE的第一件事铸造指针将不需要在所有移动指针。

If one happens to have a pointer to the "dev" field inside of a usb_device object then in order to cast it back to that usb_device object one needs to subtract 8 from that pointer. But if "dev" was the first thing in a usb_device casting the pointer wouldn't need to move the pointer at all.

任何帮助将大大AP preciated。即使咨询在哪里可以找到答案将是AP preciated - 我真的不知道如何为谷歌这样的决定背后的原因的建筑。最近,我可以在这里找到计算器是:
为什么要使用这些怪异的嵌套结构

Any help on this would be greatly appreciated. Even advice on where to find an answer would be appreciated - I'm not really sure how to Google for the architectural reason behind a decision like this. The closest I could find here on StackOverflow is: why to use these weird nesting structure

和,仅仅是明确的 - 据我所知,有很多聪明的人都在Linux内核上工作了很长一段时间,所以显然有一个很好的理由做这种方式,我只是无法弄清楚它是什么

And, just to be clear - I understand that a lot of bright people have worked on the Linux kernel for a long time so clearly there's a good reason for doing it this way, I just can't figure out what it is.

推荐答案

在Amiga的操作系统使用这种公共头招在很多地方,它看上去像在当时是个好主意。但也有缺点。

The Amiga OS uses this "common header" trick in a lot of places and it looked like a good idea at the time: Subclassing by simply casting the pointer type. But there are drawbacks.

临:


  • 您可以扩展现有的数据结构

  • 您可以使用在所有地方相同的指针,其中基本型预计,不需要指针运算,节省了precious周期

  • 感觉自然

缺点:


  • 不同的编译器往往会对齐数据结构不同。如果基础结构与结束一个烧焦; ,那么你可以有0,1或3填充字节启动子的下一个领域之后了。这导致了相当讨厌的错误,尤其是当你不得不保持向后兼容性(即出于某种原因,你必须有一定的填充,因为一个古老的编译器的版本有一个bug,现在,有很多code的其中预计马车填充)。

  • 您还不赶快在你身边传递了错误的通知结构。随着你的问题code,场得到捣毁非常快,如果指针算法是错误的。这是一件好事,因为它提出了机会,一个bug被发现得早了。

  • 它导致一种态度我的编译器将修复它为我(它有时不会),所有的强制转换导致我知道的比编译器更好的态度。后者会让你理解错误信息,这将导致各种古怪问题之前自动插入转换。

  • Different compilers tend to align data structures differently. If the base structure ended with char a;, then you could have 0, 1 or 3 pad bytes afterwards before the next field of the subclass starts. This led to quite nasty bugs, especially when you had to maintain backwards compatibility (i.e. for some reason, you have to have a certain padding because an ancient compiler version had a bug and now, there is lots of code which expects the buggy padding).
  • You don't notice quickly when you pass the wrong structure around. With the code in your question, fields get trashed very quickly if the pointer arithmetic is wrong. That is a good thing since it raises chances that a bug is discovered more early.
  • It leads to an attitude "my compiler will fix it for me" (which it sometimes won't) and all the casts lead to a "I know better than the compiler" attitude. The latter one would make you automatically insert casts before understanding the error message, which would lead to all kinds of odd problems.

Linux内核是把常见的结构别处;它可以是,但不必须是在末端。

The Linux kernel is putting the common structure elsewhere; it can be but doesn't have to be at the end.

临:


  • 虫子会过早地出现

  • 您将不得不做的每结构的一些指针运算,所以你习惯了它

  • 您不必强制转换

缺点:


  • 不明显

  • code是更复杂的

这篇关于Linux内核:为什么'子'结构把基础类信息在结束了吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆