Is there any alternative to non-ISO gcc specific extension __attribute__ on 64-bit kernels ?
Three types that i've noticed are: function attributes, type attributes and variable attributes.
eg.
i'd like to avoid using __attribute__((__packed__)) for structures passed over the network, even though some gcc based code do use it.
Any suggestions or pointers on how to entirely avoid __attribute__ usage in C systems/kernel code ?
thanks
Saifi.
Any suggestions or pointers on how to entirely avoid attribute usage in C systems/kernel code?
You can build your network packets piece by piece, copying each data element into the correct place in a char* buffer.
Pros: you don't have any alignment issues and it's generally portable, especially if you use the exact-width integer types from <stdint.h>
Cons: it's tedious and potentially error-prone
I'm assuming based on your comments that its your code you want to change, not the whole Linux kernel (etc).
Not sure about function attributes etc but specifically for attribute packed, I have done the following with no issues so far.
Basically instead of relying on the compiler to pack, you could use manual pad fields coupled with compile-time asserts.
struct foo {
u32 field1;
u16 field2;
u16 pad; // manual padding
// continue for other fields that the compiler would automatically pad for you with attribute packed
u32 field3;
};
To check your structure you can use a compile time assert, something like this:
#define CASSERT(cond, name) typedef cassert__##name[cond ? 1 : -1]
CASSERT(offsetof(foo, field1) == 0, field1_wrong);
CASSERT(offsetof(foo, field2) == 4, field2_wrong);
When your assertions are wrong, the build will fail with a helpful error and line number
Related
I would like to develop a device-driver on linux(written in C) and a user-space library wrapping all functions provided by my device-driver (also written in C). Just to make it more clear, my library wil provide the following methods:
int myOpen();
void myClose();
mySetConf(MyconfStruct conf)
etc.
The function will use the file associated to my device-driver, in particular:
myOpen will call the open() of my device-driver
myClose will call the close() of my device-driver
mySetConf will call the ioctl() of my device driver and pass the myConfStruct as a parameter to configure the device-driver using ioctl().
assume myConfStruct is a simple structure containing something like this:
typedef struct {
uint16_t var1;
uint8_t var2;
} myConfStruct;
I would like the myConfStruct to be a structure shared between both my user-application (library) and my kernel-driver using a single header.
Are there any best-practice while doing this?
I would like to have the structure defined into only one file, having it defined in multiple files seems to be quite error-prone if i plan on changing it in the future, but I understood that I should not include <linux/types.h> inside my user files and I shouldn't use <stdint.h> inside my device-driver.
So another question is also, how can I define the interface between a module and the user-application so that who is implementing the application is not forced to include any linux header?
What you are creating is a character device. The kernel documentation includes a specific section, the Linux driver implementer's guide, you should also read. Specifically, the ioctl based interfaces section, which also describes some of the considerations necessary (regarding alignment and 64-bit fields).
As to header files, see KernelHeaders article at kernelnewbies.org.
I would like to have the structure defined into only one file, having it defined in multiple files seems to be quite error-prone if i plan on changing it in the future.
No. You do specify the headers in two separate files: one for use in-kernel, and the other for use by userspace.
Kernel-userspace interface should be stable. You should take care to design your data structure so that you can extend it if necessary; preferably by adding some padding reserved for future use and required to be initialized to zero, and/or a version number at the beginning of the structure. Later versions must support all previous versions of the structure as well. Even if it is only a "toy" or "experimental" device driver, it is best to learn to do it right from the get go. This stuff is much, much harder to learn to "add afterwards"; I'm talking from deep experience here.
As a character device, you should also be prepared for the driver to be compiled on other architectures besides the one you are developing on. Even byte order ("endianness") can vary, although all Linux architectures are currently either ILP32 or LP64.
Also remember that there are several hardware architectures, including x86-64, that support both 64-bit and 32-bit userspace. So, even if you believe your driver will ever be used on x86-64, you cannot really assume the userspace is 64-bit (and not 32-bit). Look at existing code to see how it is done right; I recommend using e.g. bootlin's elixir to browse the Linux kernel sources.
Kernel-side header file should use __s8, __u8, __s16, __u16, __s32, __u32, __s64, or __u64. For pointers, use __u64, and u64_to_user_ptr().
Userspace-side header file should use <stdint.h> types (int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) and uint64_t for pointers. Use a cast via (uintptr_t) for the conversion, i.e. ptr = (void *)(uintptr_t)u64; and u64 = (uintptr_t)ptr.
Ensure all members are naturally aligned. This means that an N-bit member is preceded by k×N bits of other members, where k is either zero or a positive integer. Thus, if your structure needs an unsigned and a signed 8-bit integer (one for version, one for foo), an 16-bit signed integer (bar), and a 64-bit unsigned integer (baz), considering the version should be first, you'll probably want
struct kernel_side {
__u8 version;
__s8 foo;
__u16 bar;
__u32 padding;
__u64 baz;
};
struct userspace_side {
uint8_t version;
int8_t foo;
uint16_t bar;
uint32_t padding;
uint64_t baz;
};
You can also have character arrays and such, but do note that a single ioctl data block is limited to 8191 bytes or less in length.
If you spend some time designing your interface structures, you'll find that careful design will avoid annoying issues like compat_ support (making them just simple wrappers). Personally, I end up creating a test version with a userspace test program to see what works best, and only then decide on the data structures.
I ran into some weird issues (at compile time) with my embedded C code when I increased the size of the array from size [2] to [27] which contained structured metadata. So it is obvious that this is a nested structured style program and NOT my original work!
I remember in assembly code instructions, there used to be a JMP FAR, JMP NEAR/SHORT.. Is there any such limitations in structures (obviously there is no jump in structures). Could there be a condition that the compiler cannot assign a contiguous memory block for a structure because there is a limit to it and fails during compilation.
SOME CLUE: The fix as i recall was to move the member (array member)from original structure to another nested structure. That's the reason why i deduced that there maybe a limitation.
//STRUCTURES
typedef UINT8 P_Name_t[5];
typedef UINT8 ChipSN_t[3];
typedef struct
{
ChipSN_t ChipSN;
<other members>
} ChipIdent_t;
typedef struct Data_t
{
ChipIdent_t ReadOnlyMemID;
<other members>
} Data_t;
typedef struct
{
P_Name_t NameOfPart;
<other members>
} Log_t;
Data_t Data_Src;
typedef struct
{
P_Name_t NameOfPart;
ChipSN_t ChipSN;
}PartNum_ID_t;
typedef struct
{
PartNum_ID_t PN_ChipID[27];
<other members>;
}
According to standard, there is a limitation; but the limitation is much more than the size you mentioned here. C89 and C99 standard has the limit of 1023 structure members. See below text from the standard.
5.2.4.1 Translation limits
— 1023 members in a single structure or union
So looks like if your code is correct and limited to 1023 structure members the compiler you are using may have the limitation.
There may indeed be a limit to the number of structure elements your compiler can handle for a single structure, but as MCG quoted from the C Standard, this limit must be at least 1023 for compliant compilers and most compilers have higher limits or no practical limits at all.
I suspect the problem is elsewhere:
The Makefile for your project may have incomplete dependencies on the header file with the structure definitions: modules compiled with different definitions will be incompatible and produce undefined behavior. Remove all object files and recompile the project.
Some assembly modules may rely on the original structure layout: changing the definition will only affect the recompiled C modules.
Some library modules or OS system calls may rely on the original layout. Recompiling all libraries or even patching the OS may be required.
Some functions may rely on the original layout and use casts to access some of the structures via another type. Changing the layout may break such code, which is brittle anyway as even changing compilers may produce similar problems.
It is also possible that some of the type be multiply defined in different modules. This is poor and very error prone coding style as changing only one of the definitions will lead to undefined behavior when the object modules are linked together.
I am searching for a good way to document the following enum / typedef design in a shared library that I have inherited. There are many instances of the following pattern:
enum {
VAL1,
VAL2,
VAL3
};
typedef u_int16_t val_t;
int16_t myfunc(val_t foo);
This obviously causes problems with Doxygen's link generation.
Unfortunately, I cannot change this to the proper typedef enum { ... } val_t; structure that one would expect as this library runs on many different embedded systems ranging from native 16bit to 64bit. Per the C standard, an enum is guaranteed to be large enough to hold an int. Thus, changing these into proper typedefs promotes their size from sizeof(u_int16_t) (2 bytes) to sizeof(int) (usually 4 bytes but not always). Chaos ensues from storage size differences; nevermind the coordinated release nightmare required to rebuild all dependent software.
Given the above, is there any good way to mark in the comment block preceding the enum that the below is actually an alias for the typedef?
Failing that, I am looking for a solution that will concisely allow me to find these values from an arbitrary function signature. I can name the enums to something arbitrary (ex. val_enum_t) so I have considered both #see mentions as well as direct links using the # prefix. In both cases, another layer of links is generated.
My ideal solution would consist of the following:
One click from function signature to enumerated value list. Failing one click, as few clicks as possible.
Inline documentation for the enums using //!<.
If a direct association cannot be made, a single comment block to describe functionality which can be displayed on both the typedef as well as the enum itself.
gcc 4.7.2
c89
Hello,
I am using the Apache Portable Runtime and looking at their typedef's
typedef short apr_int16_t
typedef int apr_int16_t
typedef size_t apr_size_t /* This is basically the same, so what's the point */
etc.
So what is the point of all this?
When should you decided to use C's built-in standard data types or typedef's data types?
I just gave a example using the APR. However, I am also speaking generally as well. There is also the stdint.h header file that typedef's data types.
Many thanks for any suggestions,
In my opinion, it is better to have custom defined data types for native data types of the system as it helps in clearly distingushing the size of the types.
For Ex: A long may be 32 bit or 64 bit depending on the machine in which your code runs and the way it has been built. But, if your code specifically needs a 64 bit variable, then naming it as uint_64_t or something similar will always help in associating the size clearly.
In such cases, the code be written as:
#if _64BIT_
typedef long uint_64_t
#else
typedef long long uint_64_t
#endif
But as suggested by Mehrdad, don't use it "just for kicks". : )
Great question.
So what is the point of all this?
It's meant to be for abstraction, but like anything else, it is sometimes misused/overused.
Sometimes it's necessary for backwards compatibility (e.g. typedef VOID void in Windows), sometimes it's necessary for proper abstraction (e.g. typedef unsigned int size_t), and sometimes it's completely pointless logically, but makes typing easier (e.g. typedef char const *LPCSTR in Windows).
When should you decided to use C's built-in standard data types or typedef's data types?
If it makes something easier, or if it implements a proper abstraction barrier, use it.
What exactly that means is something you'll just have to learn over time.
But don't use it "just for kicks"!
I'm inexperienced with C, and working on a microcontroller with messages stored in arrays where each byte does something different. How do I give each element of the array a human-readable name instead of referencing them as msg[1], msg[2], etc.?
Is this what structs are for? But "you cannot make assumptions about the binary layout of a structure, as it may have padding between fields."
Should I just use macros like this? (I know "macros are bad", but the code is already full of them)
#define MSG_ID msg[0]
#define MSG_COMMAND msg[1]
Oh! Or I guess I could just do
MSG_ID = 0;
MSG_COMMAND = 1;
MSG[MSG_ID];
That's probably better, if a little uglier.
If you want to go that route, use a macro, for sure, but make them better than what you suggest:
#define MSG_ID(x) (x)[0]
#define MSG_COMMAND(x) (x)[1]
Which will allow the code to name the arrays in ways that make sense, instead of ways that work with the macro.
Otherwise, you can define constants for the indexes instead (sorry I could not come up with better names for them...):
#define IDX_MSG_ID 0
#define IDX_MSG_COMMAND 1
And macros are not bad if they are used responsibly. This kind of "simple aliasing" is one of the cases where macros help making the code easier to read and understand, provided the macros are named appropriately and well documented.
Edit: per #Lundin's comments, the best way to improve readability and safety of the code is to introduce a type and a set of functions, like so (assuming you store in char and a message is MESSAGE_SIZE long):
typedef char MESSAGE[MESSAGE_SIZE];
char get_message_id(MESSAGE msg) { return msg[0]; }
char get_message_command(MESSAGE msg) { return msg[1]; }
This method, though it brings some level of type safety and allows you to abstract the storage away from the use, also introduces call overhead, which in microcontroller world might be problematic. The compiler may alleviate some of this through inlining the functions (which you could incentize by adding the inline keyword to the definitions).
The most natural concept for naming a set of integers in C are enumerations:
enum msg_pos { msg_id, msg_command, };
By default they start counting at 0 and increment by one. You would then access a field by msg[msg_id] for example.
It's fine to use a struct if you take the time to figure out how your compiler lays them out, and structs can very useful in embedded programming. It will always lay out the members in order, but there may be padding if you are not on an 8-bit micro. GCC has a "packed" attribute you can apply to the struct to prohibit padding, and some other compilers have a similar feature.