c, linux - using pthread.h in kernel [closed]

笑着哭i 提交于 2020-01-07 09:48:40

问题


I'm trying to test the validity of a 9*9 sudoku problem and the results should be printed via printk(KERN_INFO "blablabla"). I've tried two methods to compile my c file, make and gcc myfile.c myfile -o -lpthread. However, none of them worked.

When I called make it threw me with an fatal error: pthread.h: no such file or directory but it is right in the path /usr/include.

Then I found some recommendations from the net so I tried gcc this time. Unfortunately, I got a bunch of errors after calling gcc myfile.c myfile -o -lpthread such as

/usr/include/linux/list.h: In function 'INIT_LIST_HEAD': /usr/include/linux/list.h:27:17: error: dereferencing pointer to incomplete type 'struct list_head'

and

error: unknown type name 'bool',

to name but a few. The point is that I got these errors after I upgrade my softwares via sudo apt-get update -y.

Here's the code:

#include <pthread.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

typedef struct
{
    int row;
    int col;
    int (* board)[9];
} parameters;

void * find_rows(void * params);

void * find_cols(void * params);

void * check_valid(void * params);

/***************
 * ENTRY POINT
 **************/
int thread_init(void)
{
    // ====== Create the board =======
    int board[9][9] = {
            {6, 2, 4, 5, 3, 9, 1, 8, 7},
            {5, 1, 9, 7, 2, 8, 6, 3, 4},
            {8, 3, 7, 6, 1, 4, 2, 9, 5},
            {1, 4, 3, 8, 6, 5, 7, 2, 9},
            {9, 5, 8, 2, 4, 7, 3, 6, 1},
            {7, 6, 2, 3, 9, 1, 4, 5, 8},
            {3, 7, 1, 9, 5, 6, 8, 4, 2},
            {4, 9, 6, 1, 8, 2, 5, 7, 3},
            {2, 8, 5, 4, 7, 3, 9, 1, 6}
        };

    /*int  i, j = 0;
    size_t count;
    int board[9][9];
    char *line = (char *) malloc(100);

    FILE *file;
    file = fopen("test.txt", "r");

    while(getline(&line, &count, file) != -1) {
        for (count > 0; count--; j++)
            sscanf(line, "%d", &board[i][j]);
        i++;
    }*/

    parameters * data = (parameters *) malloc(sizeof(parameters));
    data->row = 0;
    data->col = 0;
    data->board = board;

    // ====== Create the parameters for the 3x3 threads ======

    // First 3x3
    parameters * data1 = (parameters *) malloc(sizeof(parameters));
    data1->row = 0;
    data1->col = 0;
    data1->board = board;

    // Second 3x3
    parameters * data2 = (parameters *) malloc(sizeof(parameters));
    data2->row = 0;
    data2->col = 3;
    data2->board = board;

    // Third 3x3
    parameters * data3 = (parameters *) malloc(sizeof(parameters));
    data3->row = 0;
    data3->col = 6;
    data3->board = board;

    // Fourth 3x3
    parameters * data4 = (parameters *) malloc(sizeof(parameters));
    data4->row = 3;
    data4->col = 0;
    data4->board = board;

    // Fifth 3x3
    parameters * data5 = (parameters *) malloc(sizeof(parameters));
    data5->row = 3;
    data5->col = 3;
    data5->board = board;

    // Sixth 3x3
    parameters * data6 = (parameters *) malloc(sizeof(parameters));
    data6->row = 3;
    data6->col = 6;
    data6->board = board;

    // Seventh 3x3
    parameters * data7 = (parameters *) malloc(sizeof(parameters));
    data7->row = 6;
    data7->col = 0;
    data7->board = board;

    // Eighth 3x3
    parameters * data8 = (parameters *) malloc(sizeof(parameters));
    data8->row = 6;
    data8->col = 3;
    data8->board = board;

    // Ninth 3x3
    parameters * data9 = (parameters *) malloc(sizeof(parameters));
    data9->row = 6;
    data9->col = 6;
    data9->board = board;

    // ====== Create the threads ======
    pthread_t thread_rows, thread_cols, thread1, thread2, thread3, thread4, thread5, thread6, thread7, thread8, thread9;

    // ====== Create the return values for the threads ======
    void * all_rows;
    void * all_cols;
    void * square1;
    void * square2;
    void * square3;
    void * square4;
    void * square5;
    void * square6;
    void * square7;
    void * square8;
    void * square9;

    // ====== Initialize the threads ======
    pthread_create(&thread_rows, NULL, find_rows, (void *) data);
    pthread_create(&thread_cols, NULL, find_cols, (void *) data);
    pthread_create(&thread1, NULL, check_valid, (void *) data1);
    pthread_create(&thread2, NULL, check_valid, (void *) data2);
    pthread_create(&thread3, NULL, check_valid, (void *) data3);
    pthread_create(&thread4, NULL, check_valid, (void *) data4);
    pthread_create(&thread5, NULL, check_valid, (void *) data5);
    pthread_create(&thread6, NULL, check_valid, (void *) data6);
    pthread_create(&thread7, NULL, check_valid, (void *) data7);
    pthread_create(&thread8, NULL, check_valid, (void *) data8);
    pthread_create(&thread9, NULL, check_valid, (void *) data9);

    // ======= Wait for all threads to finish their tasks =======
    pthread_join(thread_rows, &all_rows);
    pthread_join(thread_cols, &all_cols);
    pthread_join(thread1, &square1);
    pthread_join(thread2, &square2);
    pthread_join(thread3, &square3);
    pthread_join(thread4, &square4);
    pthread_join(thread5, &square5);
    pthread_join(thread6, &square6);
    pthread_join(thread7, &square7);
    pthread_join(thread8, &square8);
    pthread_join(thread9, &square9);

    // ====== Check whether the Sudoku Puzzle was solved ======
    if (    (int)(uintptr_t) all_rows == 1 &&
            (int)(uintptr_t) all_cols == 1 &&
            (int)(uintptr_t) square1 == 1 &&
            (int)(uintptr_t) square2 == 1 &&
            (int)(uintptr_t) square3 == 1 &&
            (int)(uintptr_t) square4 == 1 &&
            (int)(uintptr_t) square5 == 1 &&
            (int)(uintptr_t) square6 == 1 &&
            (int)(uintptr_t) square7 == 1 &&
            (int)(uintptr_t) square8 == 1 &&
            (int)(uintptr_t) square9 == 1 )
    {
        printf("The Sudoku Puzzle is solved!\n");
    }
    else
    {
        printf("The Sudoku Puzzle is NOT solved.\n");
    }

    return 0;
}

void * find_rows(void * params) {
    parameters * data = (parameters *) params;
    int startRow = data->row;
    int startCol = data->col;
    for (int i = startRow; i < 9; ++i) {
        int row[10] = {0};
        for (int j = startCol; j < 9; ++j) {
            int val = data->board[i][j];
            if (row[val] != 0) {
                return (void *) 0;
            }
            else{
                row[val] = 1;
            }
        }
    }
    return (void *) 1;
}

void * find_cols(void * params) {
    parameters * data = (parameters *) params;
    int startRow = data->row;
    int startCol = data->col;
    for (int i = startCol; i < 9; ++i) {
        int col[10] = {0};
        for (int j = startRow; j < 9; ++j) {
            int val = data->board[j][i];
            if (col[val] != 0) {
                return (void *) 0;
            }
            else{
                col[val] = 1;
            }
        }
    }
    return (void *) 1;
}

void * check_valid(void * params) {
    parameters * data = (parameters *) params;
    int startRow = data->row;
    int startCol = data->col;
    int saved[10] = {0};
    for (int i = startRow; i < startRow + 3; ++i) {
        for (int j = startCol; j < startCol + 3; ++j) {
            int val = data->board[i][j];
            if (saved[val] != 0) {
                return (void *) 0;
            }
            else{
                saved[val] = 1;
            }
        }
    }
    return (void *) 1;
}

void thread_exit(void)
{
    printk(KERN_INFO "Removing Module\n");
}

module_init( thread_init );
module_exit( thread_exit );

I just can't figure out what went wrong...and no idea how to debug.

Thanks in advance.


回答1:


Don't use <pthread.h> in kernel code

You are very confused about the difference between kernel code and application (user-space) code. You should avoid writing kernel code. Read about CPU modes.

(you need to become a guru about C and about Linux application programming before daring writing a single line of kernel code, even a trivial kernel module)

Kernel code is for stuff like device drivers, not for Sudoku-s. Of course, you cannot use pthread in kernel code : the kernel is implementing threads by providing the clone(2) syscall to applications. The POSIX C library -your libc.so, generally the GNU glibc- is implementing pthreads(7) with the help of many system calls -listed in syscalls(2)-, including clone and futex(7).

Read Operating Systems: Three easy pieces to understand more the role of OSes.

I just can't figure out what went wrong

Your entire approach is wrong. Throw your code away.


Learn multi-threaded POSIX application programming

Read ALP (and intro(2) then intro(3)...) to learn how to write Linux application code.

Take several days to read some pthread tutorial.

Then, code some application program using Posix threads (so having a main and calling pthread_create(3) and pthread_join(3)) to solve your sudoku. You'll probably need mutexes and conditional variables for synchronization.

If you want to learn kernel programming, start with some much simpler task. Before that, become extremely fluent with Linux application programming.

(adding kernel threads is really difficult; they are not POSIX threads at all. Leave that to advanced kernel developers; learn first about user-space thread programming, it is difficult enough.)

So give up your kernel programming idea. Focus on learning C programming and POSIX application programming (that takes many years).

Compile your (user-space) code with all warnings and debug info: gcc -Wall -Wextra -g with GCC. Improve it to get no warnings. Learn to use the gcc compiler, build automation tools like GNU make or ninja, the gdb debugger, valgrind, address sanitizers and other instrumentation options.



来源:https://stackoverflow.com/questions/47052640/c-linux-using-pthread-h-in-kernel

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!