14

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).

  1. Is it a bad idea to use linux/*.h includes in user-space code?
  2. Is it a bad idea to use <stdint.h> in kernel-space code?
  3. 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?
pevik
  • 4,523
  • 3
  • 33
  • 44
Rob
  • 801
  • 2
  • 9
  • 16

2 Answers2

7
  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.

  1. Is it a bad idea to use stdint.h in kernel-space code?

Most definitely yes.

See also: http://lwn.net/Articles/113349/

sheu
  • 5,653
  • 17
  • 32
0

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.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985