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 use stdint.h in my driver module, 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).
Soo....
- 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?
Thanks.
- 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/
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-does-i