问题
I'm developing a device driver module and associated user libraries to handle the ioctl()
calls. The library takes the pertinent info and puts it into a struct, which gets passed into the driver module and unpacked there and then dealt with (I'm omitting a lot of steps, but that's the overall idea).
Some of the data being passed through the struct via the ioctl()
is uint32_t
type. I've discovered that that type is defined in <stdint.h>
AND <linux/types.h>
. So far I've been using <linux/types.h>
to define that value, including down in the user libraries. But I understand it is bad form to use <linux/*.h>
libraries in user space, so if I remove those and use <stdint.h>
instead, then when my driver module includes the struct definition, it will have to be including <stdint.h>
also.
It seems to me that the point of <linux/types.h>
is to define types in kernel files, so I'm not sure if that means using <stdint.h>
is bad idea there. I also found that when trying to compile my driver module with <stdint.h>
, I get compilation errors about redefinitions that won't go away, even if I replace all instances of <linux/types.h>
with <stdint.h>
(and put it on the top of the include order).
- Is it a bad idea to use linux/*.h includes in user-space code?
- Is it a bad idea to use
<stdint.h>
in kernel-space code? - If the answers to both of those is yes, then how do I handle the situation where a structure containing
uint32_t
is shared by both the user library and the driver module?
回答1:
- Is it a bad idea to use linux/*.h includes in user-space code?
Yes, usually. The typical situation is that you should be using the C-library headers (in this case, stdint.h
and friends), and interface with the C library though those user-space types, and let the library handle talking with the kernel through kernel types.
You're not in a typical situation though. In your case, you're writing the driver library. So you should be presenting an interface to userspace using stdint.h
, but using the linux/*.h
headers when you interface to your kernel driver.
So the answer is no, in your case.
- Is it a bad idea to use stdint.h in kernel-space code?
Most definitely yes.
See also: http://lwn.net/Articles/113349/
回答2:
Fixed length integers in the Linux kernel
The Linux kernel already has fixed length integers which might interest you. In v4.9 under include/asm-generic/int-ll64.h
:
typedef signed char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
LDD3 has a chapter about data sizes as well: https://static.lwn.net/images/pdf/LDD3/ch11.pdf
LDD3 mentions there that the best printk
strategy is to cast to just cast to the largest integer possible with correct signedness: %lld
or %llu
. %ju
appears unavailable under the printk
formatting centerpiece lib/linux/vsprintf.c
.
来源:https://stackoverflow.com/questions/14541536/using-linux-types-h-in-user-programs-or-stdint-h-in-driver-module-code-do