我是内核模块的新手。使用等待队列,我阻塞线程直到缓冲区有数据。使用hrtimer,我会定期唤醒队列。现在,问题是即使在我删除内核模块后,我也可以看到该进程"thread1"仍在运行。我认为问题是等待队列一直在等待并且进程在这里被阻塞。请帮助我如何在删除模块时终止等待队列。
void thread1(void)
{
while (thread_running) {
...
wait_event_interruptible(wait_queue, does_buffer_have_data());
...
}
}
Run Code Online (Sandbox Code Playgroud) 我正在 Ubuntu 17.04 中编写一个简单的内核模块,它接受一个字符串并将其打印在内核日志中。
#include<linux/module.h>
#include<linux/init.h>
#include<linux/moduleparam.h>
char* mystring = "hello world";
module_param(mystring ,charp ,S_IRUSR | S_IWUSR);
void display(void){
printk(KERN_ALERT "%s" ,mystring);
}
static int hello(void){
//printk(KERN_ALERT "hello module");
display();
return 0;
}
static void bye(void){
printk(KERN_ALERT "bye");
}
module_init(hello);
module_exit(bye);
Run Code Online (Sandbox Code Playgroud)
我运行命令make,然后当我运行时insmod test.ko mystring="blahblahblah",模块将被正确插入,但是当我运行时dmesg它不显示blahblahblah.
在我运行之后rmmod test.ko,dmseg该表达式blahblahblah将出现在终端中。当我运行insmod test.ko mystring="blahblahblah"一次,然后dmesg在blahblahblah将被打印出来。
究竟是什么问题?是我的问题还是系统的问题?
正如标题所示,我正在编写一个内核模块,我希望该模块创建的字符设备自动显示。我可以在我的and中使用mknodand来创建和删除设备吗?rmmodule_initmodule_exit
编辑:不确定这是否允许,但作为问题的扩展,我在哪里可以找到更多这样的信息?我的大多数谷歌搜索都会导致对非常旧的信息(内核 2.6 及更早版本)感到非常困惑,学习如何编写内核模块的最佳位置是什么?
Linux 内核模块中的一些简单预处理器代码会出现以下错误:
标记“(”之前缺少二元运算符
代码:
#if defined(AAA) || defined(BBB)
#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,13,0)
#define SOME 111
#else
#define SOME 222
#endif
#define OTHER 999
#else
#define SOME 1
#define OTHER 9
#endif /* AAA || BBB */
Run Code Online (Sandbox Code Playgroud)
那个帖子没有帮助。
我正在创建一个玩井字游戏的角色设备模块。我正在尝试对其进行编程,以便将其/dev/ticactoe模式设置为666,而不是让用户使用该chmod命令。
我的main.c包含以下内容以及和tictactoe的实现(为了简洁而进行了编辑):initexit
static dev_t device_number;
static struct cdev our_cdev;
static struct class* my_class = NULL;
static struct file_operations fops = {
.owner = THIS_MODULE,
.read = tictactoe_read,
.write = tictactoe_write,
.open = tictactoe_open,
.release = tictactoe_release,
};
Run Code Online (Sandbox Code Playgroud)
我有一个tictactoe.h包含以下内容:
#define MODULE_NAME "tictactoe"
int tictactoe_open(struct inode *pinode, struct file *pfile);
ssize_t tictactoe_read(struct file *pfile, char __user *buffer, size_t length, loff_t *offset);
ssize_t tictactoe_write(struct file *pfile, const char __user …Run Code Online (Sandbox Code Playgroud) c device-driver kernel-module linux-device-driver linux-kernel
我正在创建一个需要使用一些内核级模块的应用程序,为此我将应用程序划分为2个:一个用户级程序和一个内核级程序.
在阅读了设备驱动程序并阅读了一些教程之后,我有点困惑.
是否有设备驱动程序没有任何特定设备与之关联?除了在内核模式下工作的设备驱动程序(内核代码或其他东西)之外还有什么吗?
防病毒程序和其他此类应用程序如何在内核模式下工作?设备驱动程序是正确的方法还是我错过了什么?
我多次尝试过以下代码.
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/cdev.h>
#include<asm/uaccess.h>
#include<linux/semaphore.h>
MODULE_LICENSE("DUAL BSD/GPL");
static int dev_open(struct inode *,struct file *);
static int dev_release(struct inode *,struct file *);
ssize_t dev_read(struct file *,char *, size_t ,loff_t *);
ssize_t dev_write(struct file *,const char *,size_t ,loff_t *);
static int major;
int dev_major = 0;
int dev_minor = 0;
struct cdev *cdev;
struct device {
char array[100];
struct semaphore sem;
}chr_arr;
struct file_operations dev_ops = {
.owner = THIS_MODULE,
.read = dev_read,
.write = dev_write,
.open = dev_open,
.release …Run Code Online (Sandbox Code Playgroud) 我正在尝试进入内核模块编程.经过一番研究,我有点困惑.我的问题是,我是否需要内核源来进行模块编程?
如果是的话,在编译完我编写的模块后,是否需要重新编译内核?
我正在使用asm/i387.h中的kernel_fpu_begin和kernel_fpu_end函数来保护FPU寄存器状态,以便在Linux内核模块中进行一些简单的浮点运算.
我很好奇在kernel_fpu_begin函数之前调用函数两次的行为,kernel_fpu_end反之亦然.例如:
#include <asm/i387.h>
double foo(unsigned num){
kernel_fpu_begin();
double x = 3.14;
x += num;
kernel_fpu_end();
return x;
}
...
kernel_fpu_begin();
double y = 1.23;
unsigned z = 42;
y -= foo(z);
kernel_fpu_end();
Run Code Online (Sandbox Code Playgroud)
在foo功能,我打电话kernel_fpu_begin和kernel_fpu_end; 但是kernel_fpu_begin在打电话之前已经打过电话了foo.这会导致未定义的行为吗?
此外,我是否应该kernel_fpu_end在foo函数内部调用?我在调用后返回一个doublekernel_fpu_end,这意味着访问浮点寄存器是不安全的吗?
我最初的猜测是不要在函数内部使用kernel_fpu_begin和kernel_fpu_end调用foo; 但是如果foo将双重转换返回到unsigned而不是 - 程序员不会知道使用kernel_fpu_begin …
我是内核编程的新手,现在尝试将一些值写入设备驱动程序中的32位GPIO寄存器。I / O被ioremap()设置为内存地址。问题是,我不知道如何writel()/ writeb()/ writew()该地址写入位。
供应商文件说该寄存器已打开0xE5200000。我要写入的[0:3]位是这些位,其余的28位(这些[4:31]位)保留为零。
这是到目前为止我编写的设备驱动程序代码的一部分:
#define TCON_ADDR 0xE250000 // The address as provided by the vendor
static void *TIMER_CON_ADDR;
// I have to map and write to the address when the device is opened
static int on_dev_open(struct inode *inode, struct file *file) {
unsigned int data;
TIMER_CON_ADDR = ioremap(TCON_ADDR, 4); // Map the [0:4] bits to TIMER_CON_ADDR
data = 4; // 0100 in binary
writel(data, TIMER_CON_ADDR); …Run Code Online (Sandbox Code Playgroud) kernel-module ×10
c ×9
linux-kernel ×7
linux ×4
kernel ×3
driver ×1
gpio ×1
ioremap ×1
windows ×1