Linux Kernel : Not able to load simple linux kernel module with workqueues - linux

I'm having an issue with using the workqueues in my linux kernel module.
My modules compiles without giving any error but at the time of loading it fails.
I'm not able to load the following module and getting following error in dmesg.
[root#nanderson test_mod]# insmod workqueue_test.ko
insmod: ERROR: could not insert module workqueue_test.ko: Unknown symbol in module
[root#nanderson test_mod]# dmesg -c
[50404.453417] workqueue_test: Unknown symbol destroy_workqueue (err 0)
[50404.453437] workqueue_test: Unknown symbol __alloc_workqueue_key (err 0)
[root#nanderson test_mod]#
Following is the module code :-
1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/kthread.h>
4 #include <linux/blkdev.h>
5 #include <linux/fs.h>
6 #include <linux/delay.h>
7 #include <linux/workqueue.h>
8 #include <linux/completion.h>
9
10
11 #define LOG_ENTRY() \
12 do {\
13 printk(KERN_INFO "++ %s %d %s\n", __func__, __LINE__,\
14 current->comm);\
15 } while (0);
16
17 #define LOG_INFO() \
18 do {\
19 printk(KERN_INFO "%s %d %s\n", __func__, __LINE__,\
20 current->comm); mdelay(1000);\
21 } while (0);
22
23 #define LOG_EXIT() \
24 do {\
25 printk(KERN_INFO "-- %s %d %s\n", __func__, __LINE__,\
26 current->comm);\
27 } while (0);
28
29
30 void
31 async_callback(void *data)
32 {
33
34 }
35
36 int
37 init_module(void)
38 {
39 struct workqueue_struct *async_queue;
40
41 LOG_ENTRY();
42 if ((async_queue = create_workqueue("HGST_WORKQUEUE")) == NULL) {
43 printk(KERN_ERR "failed to create workqueue\n");
44 return -1;
45 }
46
47 mdelay(10000);
48 destroy_workqueue(async_queue);
49 LOG_EXIT();
50 return 0;
51 }
52
53
54 void
55 cleanup_module(void)
56 {
57 printk(KERN_INFO "Unloading MOdule..\n");
58 }
I also looked into /proc/kallsysm for the unknown symbols reposted by insmod looks like symbols are available following is the output:-
[root#nanderson test_mod]# cat /proc/kallsyms | grep __alloc_workqueue_key
ffffffff81084a10 T __alloc_workqueue_key
ffffffff8187a090 r __ksymtab___alloc_workqueue_key
ffffffff8188bd70 r __kcrctab___alloc_workqueue_key
ffffffff81892ba0 r __kstrtab___alloc_workqueue_key
[root#nanderson test_mod]#
Can someone tell me what might be the problem or I'm missing something ?
Thanks.

You need
MODULE_LICENSE("GPL");
in you code for use GPL symbols (exported using EXPORT_SYMBOL_GPL).
Otherwise module loader simply does not see such symbols.

Related

How to force g++ to respect #define _POSIX_C_SOURCE 200809L

I need to use strerror_r to translate error numbers into human readable messages compiled with g++ on Linux Debian Bullseye. The man page notes:
int strerror_r(int errnum, char *buf, size_t buflen);
/* XSI-compliant */
char *strerror_r(int errnum, char *buf, size_t buflen);
/* GNU-specific */
strerror_r():
The XSI-compliant version is provided if:
(_POSIX_C_SOURCE >= 200112L) && ! _GNU_SOURCE
Otherwise, the GNU-specific version is provided.
We have two different types of the return value: int or char* depending on the version defined by _POSIX_C_SOURCE. I have this small test program:
~$ cat strerror_r.c
#include <string.h>
#include <stdio.h>
// #define _POSIX_C_SOURCE 200112L
// #undef _GNU_SOURCE
#define ERROR_BUFFER_LEN (size_t)256
int main(int argc, char **argv)
{
#if _POSIX_C_SOURCE < 200112L
char* ret;
#else
int ret;
#endif
char errorBuffer[ERROR_BUFFER_LEN];
int errno;
errno = 0;
ret = strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
fprintf(stderr, "Error message by pointer = '%s'\n", ret);
fprintf(stderr, "Content of errorBuffer = '%s'\n", errorBuffer);
return 0;
}
If I compile it with gcc everything is as expected:
$ gcc strerror_r.c && ./a.out; rm a.out
Error message by pointer = '(null)'
Content of errorBuffer = 'Success'
If I compile it with g++ I get this:
$ g++ strerror_r.c && ./a.out; rm a.out
strerror_r.c: In function ‘int main(int, char**)’:
strerror_r.c:24:21: error: invalid conversion from ‘char*’ to ‘int’ [-fpermissive]
24 | ret = strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| char*
rm: cannot remove 'a.out': No such file or directory
If I try to force the needed version by uncommenting
#define _POSIX_C_SOURCE 200112L
#undef _GNU_SOURCE
I get:
$ g++ strerror_r.c && ./a.out; rm a.out
strerror_r.c:7: warning: "_POSIX_C_SOURCE" redefined
7 | #define _POSIX_C_SOURCE 200112L
|
In file included from /usr/include/x86_64-linux-gnu/bits/libc-header-start.h:33,
from /usr/include/string.h:26,
from strerror_r.c:3:
/usr/include/features.h:281: note: this is the location of the previous definition
281 | # define _POSIX_C_SOURCE 200809L
|
strerror_r.c: In function ‘int main(int, char**)’:
strerror_r.c:24:21: error: invalid conversion from ‘char*’ to ‘int’ [-fpermissive]
24 | ret = strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| char*
rm: cannot remove 'a.out': No such file or directory
What I'm missing here? Why g++ does not compile the default thread save version of strerror_r? I need that version. How can I fix it?
Reference
Feature Test Macros
You need to specify the #define and #undef directives before you include any header files, so the first few lines should look like this:
#define _POSIX_C_SOURCE 200112L
#undef _GNU_SOURCE
#include <string.h>
#include <stdio.h>
That's because those header files or internal header files they include need those values defined to choose the proper variant. If you define them after including the headers, the headers don't see the right values and they don't include the version you want.
Often people specify these values on the command like with the -D and -U arguments so they are always specified before header files are included.

DS1338 i2c Read issue

Hi I'm trying read the time from RTC-DS1338 with my linux Single Board Computer, but there is a problem with my code. I'm reading bad outputs with it.
I tried to read with i2cget -y 0 0x68 0 it works. but my code does not.
Can anybody help me ?
#include <stdio.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <errno.h>
#define I2C_ADDR 0x68
int main (void)
{
char value;
int fd;
unsigned char pData[10];
char i;
if ((fd = open("/dev/i2c-0", O_RDWR)) < 0)
{
printf("Error: Couldn't open device! %d\n", fd);
return 1;
}
if (ioctl(fd, I2C_SLAVE, I2C_ADDR) < 0)
{
printf("Error: Couldn't find device on address!\n");
return 1;
}
while (1)
{
if (read(fd, &pData, 4) != 4)
{
perror("Read conversion");
}
else
{
for(i=0;i<4;i++) printf(" %02x ",(pData[i] & 0xFF));
printf("\n");
}
sleep(2);
}
return 0;
}
Bad Output:
00 b3 49 47
4e 27 09 21
24 81 29 00
1a 20 02 10
16 1e 1a 46
1a 00 96 18
45 82 03 e0
24 40 88 1c
Good Data:
00 05 08 00
01 05 08 00
02 05 08 00
03 05 08 00
04 05 08 00
05 05 08 00
I have resolve my problem with the below code
if ((fd = open("/dev/i2c-0", O_RDWR)) < 0)
{
printf("Error: Couldn't open device! %d\n", fd);
return 1;
}
if (ioctl(fd, I2C_SLAVE, I2C_ADDR) < 0)
{
printf("Error: Couldn't find device on address!\n");
return 1;
}
if (write(fd, wData, 1) != 1)
{
perror("Write to register");
}
if (read(fd, rData, 64) != 64)
{
perror("Read conversion");
}
else
{
memcpy(Dat,rData,7);
}
close(fd);
return 0;

My strace program gave wrong output under 64bit linux system

I am building an online judge system. The key point is to trace system calls.
I choose ptrace. The subprocess will stopped because of SIGTRAP when it's going to enter one system call, then the parent process goes to read the orig_rax (orig_eax)register of subprocess to get the system call number.
When the code is running under Opensuse13.1 32bit, no problem, its output is the same as the linux command strace.
But I just test the code under Opensuse13.1 64bit, Ubuntu12.04 64bit, its output is wrong.
The demo code can be downloaded here : https://gist.github.com/kainwen/41a7bd0198099d766bda
Under 64bit linux system, you save the code strace_ls.c, compile it gcc strace_ls.c, and run it./a.out 2>out. The output is here
So my code's output is strange.
My code and its output is below:
#include <sys/resource.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/user.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
void judge_exe()
{
pid_t pid ;
int insyscall = 0 ;
struct user context ;
pid = fork() ;
if (pid == 0) { //child
ptrace(PTRACE_TRACEME,0,NULL,NULL) ;
execl("/usr/bin/ls","ls",NULL) ;
}
else {//parent
int status ;
ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
while (1) {
wait(&status) ;
if (WIFEXITED(status)) //normally terminated
break;
else if (WIFSTOPPED(status) && (WSTOPSIG(status)==SIGTRAP)) {
if (!insyscall) {
insyscall = 1;
ptrace(PTRACE_GETREGS,pid,NULL,&context.regs);
fprintf(stderr,"syscall num: %d \n",context.regs.orig_rax);
} else
insyscall = 0;
}
ptrace(PTRACE_SYSCALL,pid,NULL,NULL);
}
return;
}
}
int main(int argc, char *argv[]) {
judge_exe();
}
The output of the code above is (just heading lines):
syscall num: 59
syscall num: 12
syscall num: 9
syscall num: 21
syscall num: 2
syscall num: 4
The heading lines of output of the linux command strace ls is:
execve("/usr/bin/ls", ["ls"], [/* 101 vars */]) = 0
brk(0) = 0x1bab000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efff4326000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/usr/lib64/mpi/gcc/openmpi/lib64/tls/x86_64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib64/mpi/gcc/openmpi/lib64/tls/x86_64", 0x7fff00c49b80) = -1 ENOENT (No such file or directory)
The number of system call sys_execve is 11, not 59 (the output of my code)
Solved
My method is right. The syscall number is different under 64bit and 32bit.

Issues regarding mutexes on POSIX threads

I'm having some issues with the following code. I just can't seem to find the bug:
1 #include <pthread.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5
6 struct bla
7 {
8 pthread_mutex_t mut;
9 int x;
10 };
11
12
13 pthread_t tid;
14
15 void *thr_fn1 (struct bla *fp);
16
17 int main()
18 {
19 struct bla *fp;
20 fp = (struct bla *) malloc (sizeof(struct bla));
21 fp->x=3;
22 printf ("Initializing mutex_init\n");
23 pthread_mutex_init (&fp->mut,NULL);
24 pthread_create (&tid,NULL,thr_fn1,fp);
25 sleep (2);
26 printf ("Main thread ended sleep. Incrementing.\n");
27 fp->x++;
28 pthread_join (tid,NULL);
29 printf ("x=%d\n",fp->x);
30 pthread_mutex_destroy(&fp->mut);
31 return 0;
32
33 }
34
35 void *thr_fn1 (struct bla *fp)
36 {
37 printf ("Locking new thread!\n");
38 pthread_mutex_lock (&fp->mut);
39 printf ("Sleeping.\n");
40 sleep (5);
41 pthread_mutex_unlock (&fp->mut);
42 printf ("Thread unlocked.\n");
43 return ((void *) 0);
44 }
Why does the value still get incremented at line 27? Shouldn't it be protected by the mutex in the second thread by the lock (line 38)?
Thanks!
There is no automatic association between mutexes and data. If you want a mutex to protect some particular set of data, you are responsible for locking and unlocking the mutex around accesses to that data:
sleep (2);
pthread_mutex_lock(&fp->mut);
printf ("Main thread ended sleep. Incrementing.\n");
fp->x++;
pthread_mutex_unlock(&fp->mut);

remote debugging gdb multiple process

I am unable to debug a child process of a remote debugging session. I found a similar question How to debug the entry-point of fork-exec process in GDB?
I am following the same procedure, although for a remote target. Is follow-fork-mode child supported for remote targets ?
Following is my sample code..
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <unistd.h>
5
6 int spawn (void)
7 {
8 pid_t child_pid;
9 /* Duplicate this process. */
10 child_pid = fork ();
11 if (child_pid != 0)
12 /* This is the parent process. */
13 return child_pid;
14 else {
15 /* Now execute PROGRAM, searching for it in the path. */
16 while(1)
17 {
18 static int i = 0;
19 if(i==0) /* break here for child */
20 {
21 printf("I am child\n");
22 }
23 else if(i==3)
24 {
25 return 1;
26 }
27 else
28 {
29 i = 0/0;
30 }
31 i++;
32 }
33 }
34 return 0;
35 }
36 int main ()
37 {
38 /* Spawn a child process running the .ls. command. Ignore the
39 returned child process ID. */
40 printf("Hello World..!!\n");
41 spawn ();
42 printf ("Bbye World..!!\n");
43 return 0;
44 }
Running it with gdb, I can set set break point in child.. all fine here.!!
sh-3.2# gdb fork
(gdb) set follow-fork-mode child
(gdb) set detach-on-fork off
(gdb) b 19
Breakpoint 1 at 0x80483d0: file fork-exec.c, line 19.
(gdb) c
The program is not being run.
(gdb) start
Breakpoint 2 at 0x8048437: file fork-exec.c, line 40.
Starting program: fork
main () at fork-exec.c:40
40 printf("Hello World..!!\n");
(gdb) c
Continuing.
Hello World..!!
[Switching to process 10649]
Breakpoint 1, spawn () at fork-exec.c:19
19 if(i==0) /* break here for child */
(gdb)
However if I try to catch child via gdbserver break point is lost..
sh-3.2# gdbserver :1234 fork &
[5] 10686
sh-3.2# Process fork created; pid = 10689
Listening on port 1234
Run as target remote
sh-3.2# gdb fork
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
Remote debugging from host 127.0.0.1
[New Thread 10689]
0x00bd2810 in _start () from /lib/ld-linux.so.2
(gdb) break 19
Breakpoint 1 at 0x80483d0: file fork-exec.c, line 19.
(gdb) c
Continuing.
Hello World..!!
Bbye World..!!
Child exited with retcode = 0
Program exited normally.
Child exited with status 0
GDBserver exiting
What is the procedure to debug child process in embedded world. I know I can do a process attach, but I want to debug from the very beginning of the child process..
It is called follow-fork. No, it is not supported in gdbserver.
As a (dirty!) workaround, you can just add a sleep() call right after the fork() with a delay long enough for you to get the child PID, attach it with another instance of gdbserver and connect to it with gdb.
It should work with a modern gdb version, according to this bug-report.

Resources