Passing struct to device driver through IOCTL - linux

I am trying to pass a struct from user space to kernel space. I had been trying for many hours and it isn't working. Here is what I have done so far..
int device_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg){
int ret, SIZE;
switch(cmd){
case PASS_STRUCT_ARRAY_SIZE:
SIZE = (int *)arg;
if(ret < 0){
printk("Error in PASS_STRUCT_ARRAY_SIZE\n");
return -1;
}
printk("Struct Array Size : %d\n",SIZE);
break;
case PASS_STRUCT:
struct mesg{
int pIDs[SIZE];
int niceVal;
};
struct mesg data;
ret = copy_from_user(&data, arg, sizeof(*data));
if(ret < 0){
printk("PASS_STRUCT\n");
return -1;
}
printk("Message PASS_STRUCT : %d\n",data.niceVal);
break;
default :
return -ENOTTY;
}
return 0;
}
I have trouble defining the struct. What is the correct way to define it? I want to have int pIDs[SIZE]. Will int *pIDs do it(in user space it is defined like pIDs[SIZE])?
EDIT:
With the above change I get this error? error: expected expression before 'struct' any ideas?

There are two variants of the structure in your question.
struct mesg1{
int *pIDs;
int niceVal;
};
struct mesg2{
int pIDs[SIZE];
int niceVal;
};
They are different; in case of mesg1 you has pointer to int array (which is outside the struct). In other case (mesg2) there is int array inside the struct.
If your SIZE is fixed (in API of your module; the same value used in user- and kernel- space), you can use second variant (mesg2).
To use first variant of structure (mesg1) you may add field size to the structure itself, like:
struct mesg1{
int pIDs_size;
int *pIDs;
int niceVal;
};
and fill it with count of ints, pointed by *pIDs.
PS: And please, never use structures with variable-sized arrays in the middle of the struct (aka VLAIS). This is proprietary, wierd, buggy and non-documented extension to C language by GCC compiler. Only last field of struct can be array with variable size (VLA) according to international C standard. Some examples here: 1 2
PPS:
You can declare you struct with VLA (if there is only single array with variable size):
struct mesg2{
int niceVal;
int pIDs[];
};
but you should be careful when allocating memory for such struct with VLA

Related

Correct initialisation syntax with char in struct

What is the correct syntax of a struct with char arrays ?
the nvsName gives me an error while compiling
And: is there another way to get initialize a value if the type is unknown ? Here I use the void*.
typedef struct
{
char nvsName[];
uint8_t type;
void* p;
} NVS_CONFIG;
NVS_CONFIG nvs = {'123',0,(void*)VdmConfig.configFlash.netConfig.staticIp};
your code contains multiple problems:
first : '123' is characther constant (see : wikipedia) not a string as you would expect with "123" and characther constant is an int.
second : nvsNames shoud be a pointer or have a constant size otherwise your code will not compile.
typedef struct
{
char * nvsName;
uint8_t type;
void* p;
} NVS_CONFIG;
NVS_CONFIG nvs = {"123",0,(void*)VdmConfig.configFlash.netConfig.staticIp};
should at least fix the probems you currently have.

Adding a field to msgbuf

I got an assignment to create a message queue in Linux. I need to use msgnd() and msgrcv() functions. Everything works if my message structure has two fields mtype and mtext[] but I need to add one more field an int mpid. But when I read the value from mpid it is just garbage from the memory. I searched for answers or examples but I only found structures with two fields. Can I even add more?
struct myBuff{
long mtype;
char mtext[255];
int mpid;
};
code for the sender
void add_message(int id, struct myBuff buff){
int size = strlen(buff.mtext) + 1 + sizeof(int)
if (size > 255 + sizeof(int))
exit(EXIT_FAILURE);
msgsnd(id, (struct msgbuf*)&buff, size, 0 | MSG_NOERROR);
}
code for the receiver
void check_message(int id, struct myBuff* buff)
{
msgrcv(id, (struct msgbuf*)buff, 255 + sizeof(int), buff->mtype, 0 | MSG_NOERROR);
}

Dynamic memory in a struct

So, my struct is like this:
struct player{
char name[20];
int time;
}s[50];
I don't know how many players i am going to add to the struct, and i also have to use dynamic memory for this. So how can i allocate and reallocate more space when i add a player to my struct?
I am inexperienced programmer, but i have been googling for this for a long time and i also don't perfectly understand structs.
This site doesn't accept my question so let's put some more text to this post
I assume you are programming in C/C++.
Your struct player has static-allocated fields, so, when you use malloc on it, you are asking space for a 20-byte char array a for one integer.
My suggestion is to store in a variable (or #define a symbol) the initial number of structures you can accept. Then, use malloc to allocate a static array that contains these structures.
Also you have to think about a strategy to store new players coming. The simplest one could be have an index variable to store last free position and use it to add over that position.
A short example follows:
#define init_cap 50
struct player {
char name[20];
int time;
};
int main() {
int index;
struct player* players;
players = (struct player*) malloc(init_cap * sizeof(struct player));
for(i = 0; i < init_cap; i++) {
strcpy(players[i].name, "peppe");
players[i].time = i;
}
free(players);
return 0;
}
At this point you should also think about reallocating memory if the number of players you get a runtime exceeds your initial capacity. You can use:
players = (struct player*) realloc(2 * init_cap * sizeof(struct player));
in order to double the initial capacity.
At the end, always remember to free the requested memory.

Error: this declaration has no storage class or type specifier ( Me making a simple struct. )

I was trying to make a simple struct to hold character stats.
This is what I came up with:
struct cStats
{
int nStrength;
int nIntelligence;
int nMedical;
int nSpeech;
int nAim;
};
cStats mainchar;
mainchar.nStrength = 10;
mainchar.nIntelligence = 10;
mainchar.nMedical = 10;
mainchar.nSpeech = 10;
mainchar.nAim = 10;
The mainchar. part is underlined red in visual studio, and when I mouse over it it shows this:
Error: this declaration has no storage class or type specifier
Any explanation of why it's doing this, and what I should be doing to fix it would be appreciated.
If this is C you should tag your question as such. cStats is a structure tag, not a type specifier. You need to declare mainchar as:
struct cStats mainchar;
If you wanted to use cStats as a type specifier you would define it as:
typedef struct
{
int nStrength;
int nIntelligence;
int nMedical;
int nSpeech;
int nAim;
} cStats;
If you did that your cStats mainchar would work.
Note that in C, char and character mean “ASCII alphanumeric character”, not “character in a play or game”. I suggest coming up with a different term for your program.
Another bit of advice; do not prefix your names with their data type; like nStrength for integer Strength. The compiler will tell you if you get your data types wrong, and if you ever need to change a type, for example to float nStrength to handle fractional Strengths, changing the name will be a big problem.
main(){
mainchar.nStrength = 10;
mainchar.nIntelligence = 10;
mainchar.nMedical = 10;
mainchar.nSpeech = 10;
mainchar.nAim = 10;}
These initialization should be written within the main() function.
Or else, write a init function and call it from main function.

allocating enough memory using typedef struct object whose size varies in another typedef struct

I have defined two typedef structs, and the second has the first as an object:
typedef struct
{
int numFeatures;
float* levelNums;
} Symbol;
typedef struct
{
int numSymbols;
Symbol* symbols;
} Data_Set;
I then defined numFeatures and numSymbols and allocate memory for both symbols and levelNums, then fill levelNums inside a for loop with value of the inner loop index just to verify it is working as expected.
Data_Set lung_cancer;
lung_cancer.numSymbols = 5;
lung_cancer.symbols = (Symbol*)malloc( lung_cancer.numSymbols * sizeof( Symbol ) );
lung_cancer.symbols->numFeatures = 3;
lung_cancer.symbols->levelNums = (float*)malloc( lung_cancer.symbols->numFeatures * sizeof( float ) );
for(int symbol = 0; symbol < lung_cancer.numSymbols; symbol++ )
for( int feature = 0; feature < lung_cancer.symbols->numFeatures; feature++ )
*(lung_cancer.symbols->levelNums + symbol * lung_cancer.symbols->numFeatures + feature ) = feature;
for(int symbol = 0; symbol < lung_cancer.numSymbols; symbol++ )
for( int feature = 0; feature < lung_cancer.symbols->numFeatures; feature++ )
cout << *(lung_cancer.symbols->levelNums + symbol * lung_cancer.symbols->numFeatures + feature ) << endl;
return 0;
When levelNums are int I get what I expect( i.e. 0,1,2,0,1,2,...) but when they are float, only the first 3 are correct and the remaining are very small or very large values, not 0,1,2 like expected. I then have two questions:
When allocating memory for symbols, how does it know how big a Symbol is since I have not yet defined how large levelNums will be yet.
How do I get float values into levelNums correctly.
The reason I am doing it like this is this is a data structure that will be sent to a GPU for GPGPU programming in CUDA and arrays are not recognized. I can only send in a continuous block of memory explicitly and the typedef structs are only there for conveying/defining the memory struture of the data.
A couple thing jump out at meet. For one thing, you only allocated a buffer for levelNums of the first symbol. Similarly, your inner loops always loop over the numFeatures of the first symbol.
You're doing a whole lot of dereferencing of arrays, which is fine in general, but the assignment in particular (inside the first set of loops) looks very strange. It's entirely possible I just don't understand what you're trying to do there, but I think it'd be a lot less confusing if you used some square bracket array accessors.

Resources