问题
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