Sunday, February 20, 2022

[SOLVED] Tagged structure initialization, functions and their parameters

Issue

Many Kernel modules seem to opt for the following struct initialization style;

struct file_operations sample_fops = {
.owner = THIS_MODULE,
.read = sample_read,
.write = sample_write,
.ioctl = sample_ioctl,
.open = sample_open,
.release = sample_release,
};

I can wrap my head around when this style is used for primitives and pointer data types but I can't figure out how they work so seamlessly for functions.

When and where are the parameters for this type of initialization created? Is it in the scope of the file or in the scope where the struct is utilized. Can you access the parameters (for instance a pointer to buffer passed as an argument to the write function) or do you have to initialize the struct in a different style in order to be able to do that?

Furthermore, if sample_fops is called multiple times, is it the same struct throughout the file? And where is it kept in the memory during its lifetime? Are the parameters kept in the same place too?


Solution

I have not exactly understood your question but this is

struct file_operations sample_fops = {
.owner = THIS_MODULE,
.read = sample_read,
.write = sample_write,
.ioctl = sample_ioctl,
.open = sample_open,
.release = sample_release,
};

a declaration of the object sample_fops that has the type struct file_operations.

It seems that the data members of the structure are declared as pointers to functions and in this declaration function designators as for example sample_open are used to initializa corresponding data members of the structure.

Here is a demonstrative program.

#include <stdio.h>

void f( void )
{
    puts( "Hello Yusuf Gürkan Bor" );
}

struct A
{
    void ( *hello )( void );    
};

int main( void )
{
    struct A a = { .hello = f };

    a.hello();
}

The program output is

Hello Yusuf Gürkan Bor

This record in the initializarion .fp = f is called a designation initialization. It uses the name of a data member of a structure that is initialized.

In fact you can equivalently to write

struct A a = { f };

But for a such an initialization you have to keep the order of initializers relative to the order of data members.

Here is another example when a function accepts an argument.

#include <stdio.h>

void f( const char *name )
{
    printf( "Hello %s\n", name );
}

struct A
{
    void ( *hello )( const char * );    
};

int main( void )
{
    struct A a = { .hello = f };

    a.hello( "Yusuf Gürkan Bor" );
}

Its output is the same as shown above.



Answered By - Vlad from Moscow
Answer Checked By - Cary Denson (WPSolving Admin)