以下为你提供20个Linux驱动开发的实用案例,涵盖字符设备驱动、块设备驱动、网络设备驱动等不同类型,包含应用场景、技巧、代码示例和操作步骤。先赞再看后评论,腰缠万贯财进门
。
用于实现基本的设备文件读写操作,例如模拟一个简单的传感器设备。
使用cdev
结构体来注册字符设备,实现file\_operations
结构体中的读写函数。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#define DEVICE\_NAME "simple\_char\_dev"
#define BUFFER\_SIZE 100
static char buffer[BUFFER\_SIZE];
static int major;
static ssize\_t simple\_read(struct file \*filp, char \_\_user \*buf, size\_t count, loff\_t \*f\_pos) {
if (\*f\_pos >= BUFFER\_SIZE)
return 0;
if (\*f\_pos + count > BUFFER\_SIZE)
count = BUFFER\_SIZE - \*f\_pos;
if (copy\_to\_user(buf, buffer + \*f\_pos, count))
return -EFAULT;
\*f\_pos += count;
return count;
}
static ssize\_t simple\_write(struct file \*filp, const char \_\_user \*buf, size\_t count, loff\_t \*f\_pos) {
if (\*f\_pos >= BUFFER\_SIZE)
return -ENOSPC;
if (\*f\_pos + count > BUFFER\_SIZE)
count = BUFFER\_SIZE - \*f\_pos;
if (copy\_from\_user(buffer + \*f\_pos, buf, count))
return -EFAULT;
\*f\_pos += count;
return count;
}
static struct file\_operations fops = {
.read = simple\_read,
.write = simple\_write,
};
static int \_\_init simple\_char\_init(void) {
major = register\_chrdev(0, DEVICE\_NAME, &fops);
if (major < 0) {
printk(KERN\_ALERT "Registering char device failed with %d\n", major);
return major;
}
printk(KERN\_INFO "I was assigned major number %d.\n", major);
return 0;
}
static void \_\_exit simple\_char\_exit(void) {
unregister\_chrdev(major, DEVICE\_NAME);
printk(KERN\_INFO "Simple char device module unloaded.\n");
}
module\_init(simple\_char\_init);
module\_exit(simple\_char\_exit);
MODULE\_LICENSE("GPL");
simple\_char.c
。Makefile
:obj-m += simple\_char.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
make
sudo insmod simple\_char.ko
sudo mknod /dev/simple\_char c $(major) 0
echo "Hello, World!" > /dev/simple\_char
cat /dev/simple\_char
sudo rmmod simple\_char
当多个进程可能同时访问设备时,需要使用互斥锁来保证数据的一致性。
使用mutex
结构体来实现互斥访问。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/mutex.h>
#define DEVICE\_NAME "mutex\_char\_dev"
#define BUFFER\_SIZE 100
static char buffer[BUFFER\_SIZE];
static int major;
static DEFINE\_MUTEX(mutex);
static ssize\_t mutex\_read(struct file \*filp, char \_\_user \*buf, size\_t count, loff\_t \*f\_pos) {
ssize\_t ret;
if (!mutex\_trylock(&mutex))
return -EBUSY;
if (\*f\_pos >= BUFFER\_SIZE)
ret = 0;
else {
if (\*f\_pos + count > BUFFER\_SIZE)
count = BUFFER\_SIZE - \*f\_pos;
if (copy\_to\_user(buf, buffer + \*f\_pos, count))
ret = -EFAULT;
else {
\*f\_pos += count;
ret = count;
}
}
mutex\_unlock(&mutex);
return ret;
}
static ssize\_t mutex\_write(struct file \*filp, const char \_\_user \*buf, size\_t count, loff\_t \*f\_pos) {
ssize\_t ret;
if (!mutex\_trylock(&mutex))
return -EBUSY;
if (\*f\_pos >= BUFFER\_SIZE)
ret = -ENOSPC;
else {
if (\*f\_pos + count > BUFFER\_SIZE)
count = BUFFER\_SIZE - \*f\_pos;
if (copy\_from\_user(buffer + \*f\_pos, buf, count))
ret = -EFAULT;
else {
\*f\_pos += count;
ret = count;
}
}
mutex\_unlock(&mutex);
return ret;
}
static struct file\_operations fops = {
.read = mutex\_read,
.write = mutex\_write,
};
static int \_\_init mutex\_char\_init(void) {
major = register\_chrdev(0, DEVICE\_NAME, &fops);
if (major < 0) {
printk(KERN\_ALERT "Registering char device failed with %d\n", major);
return major;
}
printk(KERN\_INFO "I was assigned major number %d.\n", major);
return 0;
}
static void \_\_exit mutex\_char\_exit(void) {
unregister\_chrdev(major, DEVICE\_NAME);
printk(KERN\_INFO "Mutex char device module unloaded.\n");
}
module\_init(mutex\_char\_init);
module\_exit(mutex\_char\_exit);
MODULE\_LICENSE("GPL");
与简单字符设备驱动类似,只是编译和加载的是mutex\_char.ko
。
周期性地执行某个任务,例如定时采集传感器数据。
使用timer\_list
结构体和mod\_timer
函数来实现定时器。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
#define TIMEOUT 5000 // 5 seconds
static struct timer\_list my\_timer;
static void timer\_callback(unsigned long data) {
printk(KERN\_INFO "Timer callback fired!\n");
mod\_timer(&my\_timer, jiffies + msecs\_to\_jiffies(TIMEOUT));
}
static int \_\_init timer\_init(void) {
setup\_timer(&my\_timer, timer\_callback, 0);
mod\_timer(&my\_timer, jiffies + msecs\_to\_jiffies(TIMEOUT));
printk(KERN\_INFO "Timer initialized.\n");
return 0;
}
static void \_\_exit timer\_exit(void) {
del\_timer(&my\_timer);
printk(KERN\_INFO "Timer removed.\n");
}
module\_init(timer\_init);
module\_exit(timer\_exit);
MODULE\_LICENSE("GPL");
timer.c
,编写Makefile
并编译。sudo insmod timer.ko
dmesg
sudo rmmod timer
处理硬件中断,例如按键按下等事件。
使用request\_irq
函数来注册中断处理函数。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#define IRQ\_NUMBER 1
static irqreturn\_t irq\_handler(int irq, void \*dev\_id) {
printk(KERN\_INFO "Interrupt received!\n");
return IRQ\_HANDLED;
}
static int \_\_init irq\_init(void) {
int ret;
ret = request\_irq(IRQ\_NUMBER, irq\_handler, IRQF\_SHARED, "my\_irq", (void \*)(irq\_handler));
if (ret) {
printk(KERN\_ALERT "Failed to register IRQ %d\n", IRQ\_NUMBER);
return ret;
}
printk(KERN\_INFO "IRQ registered successfully.\n");
return 0;
}
static void \_\_exit irq\_exit(void) {
free\_irq(IRQ\_NUMBER, (void \*)(irq\_handler));
printk(KERN\_INFO "IRQ freed.\n");
}
module\_init(irq\_init);
module\_exit(irq\_exit);
MODULE\_LICENSE("GPL");
irq.c
,编写Makefile
并编译。sudo insmod irq.ko
dmesg
sudo rmmod irq
在后台执行一些长时间运行的任务,例如数据处理。
使用kthread\_create
和wake\_up\_process
函数来创建和启动内核线程。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kthread.h>
static struct task\_struct \*my\_thread;
static int thread\_function(void \*data) {
while (!kthread\_should\_stop()) {
printk(KERN\_INFO "Kernel thread is running...\n");
msleep(1000);
}
return 0;
}
static int \_\_init kthread\_init(void) {
my\_thread = kthread\_create(thread\_function, NULL, "my\_thread");
if (IS\_ERR(my\_thread)) {
printk(KERN\_ALERT "Failed to create kernel thread.\n");
return PTR\_ERR(my\_thread);
}
wake\_up\_process(my\_thread);
printk(KERN\_INFO "Kernel thread created and started.\n");
return 0;
}
static void \_\_exit kthread\_exit(void) {
kthread\_stop(my\_thread);
printk(KERN\_INFO "Kernel thread stopped.\n");
}
module\_init(kthread\_init);
module\_exit(kthread\_exit);
MODULE\_LICENSE("GPL");
kthread.c
,编写Makefile
并编译。sudo insmod kthread.ko
dmesg
sudo rmmod kthread
模拟一个简单的块设备,例如虚拟磁盘。
使用gendisk
结构体和block\_device\_operations
结构体来实现块设备驱动。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/blkdev.h>
#define KERNEL\_SECTOR\_SIZE 512
#define DISK\_SIZE (1024 \* 1024) // 1MB
static struct gendisk \*my\_disk;
static struct request\_queue \*my\_queue;
static unsigned char \*disk\_data;
static void my\_request(struct request\_queue \*q) {
struct request \*rq;
while ((rq = blk\_fetch\_request(q)) != NULL) {
if (blk\_rq\_is\_passthrough(rq)) {
printk(KERN\_ERR "Skip non-fs request\n");
\_\_blk\_end\_request\_all(rq, -EIO);
continue;
}
sector\_t start\_sector = blk\_rq\_pos(rq);
unsigned int sectors = blk\_rq\_sectors(rq);
void \*buffer = bio\_data(rq->bio);
if (rq\_data\_dir(rq) == READ) {
memcpy(buffer, disk\_data + start\_sector \* KERNEL\_SECTOR\_SIZE, sectors \* KERNEL\_SECTOR\_SIZE);
} else {
memcpy(disk\_data + start\_sector \* KERNEL\_SECTOR\_SIZE, buffer, sectors \* KERNEL\_SECTOR\_SIZE);
}
\_\_blk\_end\_request\_all(rq, 0);
}
}
static struct block\_device\_operations my\_fops = {
.owner = THIS\_MODULE,
};
static int \_\_init block\_init(void) {
disk\_data = vmalloc(DISK\_SIZE);
if (!disk\_data) {
printk(KERN\_ALERT "Failed to allocate disk data.\n");
return -ENOMEM;
}
my\_queue = blk\_init\_queue(my\_request, NULL);
if (!my\_queue) {
printk(KERN\_ALERT "Failed to initialize request queue.\n");
vfree(disk\_data);
return -ENOMEM;
}
my\_disk = alloc\_disk(1);
if (!my\_disk) {
printk(KERN\_ALERT "Failed to allocate gendisk.\n");
blk\_cleanup\_queue(my\_queue);
vfree(disk\_data);
return -ENOMEM;
}
my\_disk->major = register\_blkdev(0, "my\_block\_dev");
my\_disk->first\_minor = 0;
my\_disk->fops = &my\_fops;
my\_disk->queue = my\_queue;
sprintf(my\_disk->disk\_name, "my\_block\_dev");
set\_capacity(my\_disk, DISK\_SIZE / KERNEL\_SECTOR\_SIZE);
add\_disk(my\_disk);
printk(KERN\_INFO "Block device initialized.\n");
return 0;
}
static void \_\_exit block\_exit(void) {
del\_gendisk(my\_disk);
put\_disk(my\_disk);
unregister\_blkdev(my\_disk->major, "my\_block\_dev");
blk\_cleanup\_queue(my\_queue);
vfree(disk\_data);
printk(KERN\_INFO "Block device removed.\n");
}
module\_init(block\_init);
module\_exit(block\_exit);
MODULE\_LICENSE("GPL");
block.c
,编写Makefile
并编译。sudo insmod block.ko
lsblk
sudo mkfs.ext4 /dev/my\_block\_dev
sudo mkdir /mnt/my\_block
sudo mount /dev/my\_block\_dev /mnt/my\_block
sudo umount /mnt/my\_block
sudo rmmod block
用于控制 LED 实现呼吸灯效果,常见于智能家居、嵌入式设备的状态指示等场景。
利用 PWM(脉冲宽度调制)技术,通过调整占空比来改变 LED 的亮度。在 Linux 内核中,通常使用硬件的 PWM 控制器,并通过相关的内核接口进行配置和操作。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pwm.h>
#define PWM\_CHIP\_ID 0
#define PWM\_PERIOD\_NS 1000000 // 1ms period
#define PWM\_MIN\_DUTY\_NS 0
#define PWM\_MAX\_DUTY\_NS 1000000
static struct pwm\_device \*pwm\_dev;
static int \_\_init pwm\_led\_init(void) {
pwm\_dev = pwm\_request(PWM\_CHIP\_ID, "pwm\_led");
if (IS\_ERR(pwm\_dev)) {
printk(KERN\_ALERT "Failed to request PWM device.\n");
return PTR\_ERR(pwm\_dev);
}
pwm\_config(pwm\_dev, PWM\_MIN\_DUTY\_NS, PWM\_PERIOD\_NS);
pwm\_enable(pwm\_dev);
printk(KERN\_INFO "PWM LED initialized.\n");
return 0;
}
static void \_\_exit pwm\_led\_exit(void) {
pwm\_disable(pwm\_dev);
pwm\_free(pwm\_dev);
printk(KERN\_INFO "PWM LED removed.\n");
}
module\_init(pwm\_led\_init);
module\_exit(pwm\_led\_exit);
MODULE\_LICENSE("GPL");
pwm\_led.c
,编写 Makefile
并编译。sudo insmod pwm\_led.ko
/sys/class/pwm/pwmchipX/pwmY/duty\_cycle
文件来动态调整占空比,例如:echo 500000 > /sys/class/pwm/pwmchip0/pwm0/duty\_cycle
sudo rmmod pwm\_led
用于与 I2C 接口的传感器进行通信,如温度传感器、加速度计等。
使用 Linux 内核的 I2C 子系统,通过 i2c\_client
和 i2c\_driver
结构体来实现与 I2C 设备的交互。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#define I2C\_DEVICE\_ADDR 0x50
static int my\_i2c\_probe(struct i2c\_client \*client, const struct i2c\_device\_id \*id) {
u8 data;
int ret;
ret = i2c\_smbus\_read\_byte(client);
if (ret < 0) {
printk(KERN\_ALERT "Failed to read from I2C device.\n");
return ret;
}
data = (u8)ret;
printk(KERN\_INFO "Read data from I2C device: 0x%02x\n", data);
return 0;
}
static int my\_i2c\_remove(struct i2c\_client \*client) {
printk(KERN\_INFO "I2C device removed.\n");
return 0;
}
static const struct i2c\_device\_id my\_i2c\_id[] = {
{ "my\_i2c\_device", 0 },
{ }
};
MODULE\_DEVICE\_TABLE(i2c, my\_i2c\_id);
static struct i2c\_driver my\_i2c\_driver = {
.driver = {
.name = "my\_i2c\_driver",
.owner = THIS\_MODULE,
},
.probe = my\_i2c\_probe,
.remove = my\_i2c\_remove,
.id\_table = my\_i2c\_id,
};
static int \_\_init i2c\_driver\_init(void) {
return i2c\_add\_driver(&my\_i2c\_driver);
}
static void \_\_exit i2c\_driver\_exit(void) {
i2c\_del\_driver(&my\_i2c\_driver);
}
module\_init(i2c\_driver\_init);
module\_exit(i2c\_driver\_exit);
MODULE\_LICENSE("GPL");
i2c\_driver.c
,编写 Makefile
并编译。sudo insmod i2c\_driver.ko
dmesg
sudo rmmod i2c\_driver
用于与 SPI 接口的设备进行通信,如 SPI 闪存、SPI 显示屏等。
使用 Linux 内核的 SPI 子系统,通过 spi\_device
和 spi\_driver
结构体来实现与 SPI 设备的交互。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#define SPI\_DEVICE\_MODE SPI\_MODE\_0
#define SPI\_DEVICE\_BITS\_PER\_WORD 8
#define SPI\_DEVICE\_MAX\_SPEED\_HZ 1000000
static int my\_spi\_probe(struct spi\_device \*spi) {
u8 tx\_buf[1] = { 0xAA };
u8 rx\_buf[1];
struct spi\_transfer xfer = {
.tx\_buf = tx\_buf,
.rx\_buf = rx\_buf,
.len = 1,
};
struct spi\_message msg;
spi\_message\_init(&msg);
spi\_message\_add\_tail(&xfer, &msg);
if (spi\_sync(spi, &msg)) {
printk(KERN\_ALERT "SPI transfer failed.\n");
return -EIO;
}
printk(KERN\_INFO "Received data from SPI device: 0x%02x\n", rx\_buf[0]);
return 0;
}
static int my\_spi\_remove(struct spi\_device \*spi) {
printk(KERN\_INFO "SPI device removed.\n");
return 0;
}
static const struct spi\_device\_id my\_spi\_id[] = {
{ "my\_spi\_device", 0 },
{ }
};
MODULE\_DEVICE\_TABLE(spi, my\_spi\_id);
static struct spi\_driver my\_spi\_driver = {
.driver = {
.name = "my\_spi\_driver",
.owner = THIS\_MODULE,
},
.probe = my\_spi\_probe,
.remove = my\_spi\_remove,
.id\_table = my\_spi\_id,
};
static int \_\_init spi\_driver\_init(void) {
return spi\_register\_driver(&my\_spi\_driver);
}
static void \_\_exit spi\_driver\_exit(void) {
spi\_unregister\_driver(&my\_spi\_driver);
}
module\_init(spi\_driver\_init);
module\_exit(spi\_driver\_exit);
MODULE\_LICENSE("GPL");
spi\_driver.c
,编写 Makefile
并编译。sudo insmod spi\_driver.ko
dmesg
sudo rmmod spi\_driver
用于识别连接到系统的 USB 设备,如 USB 鼠标、USB 键盘等。
使用 Linux 内核的 USB 子系统,通过 usb\_driver
结构体来实现 USB 设备的识别和处理。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/usb.h>
#define USB\_VENDOR\_ID 0x1234
#define USB\_PRODUCT\_ID 0x5678
static int my\_usb\_probe(struct usb\_interface \*intf, const struct usb\_device\_id \*id) {
printk(KERN\_INFO "USB device connected: Vendor ID 0x%04x, Product ID 0x%04x\n",
id->idVendor, id->idProduct);
return 0;
}
static void my\_usb\_disconnect(struct usb\_interface \*intf) {
printk(KERN\_INFO "USB device disconnected.\n");
}
static struct usb\_device\_id my\_usb\_id\_table[] = {
{ USB\_DEVICE(USB\_VENDOR\_ID, USB\_PRODUCT\_ID) },
{ }
};
MODULE\_DEVICE\_TABLE(usb, my\_usb\_id\_table);
static struct usb\_driver my\_usb\_driver = {
.name = "my\_usb\_driver",
.probe = my\_usb\_probe,
.disconnect = my\_usb\_disconnect,
.id\_table = my\_usb\_id\_table,
};
static int \_\_init usb\_driver\_init(void) {
return usb\_register(&my\_usb\_driver);
}
static void \_\_exit usb\_driver\_exit(void) {
usb\_deregister(&my\_usb\_driver);
}
module\_init(usb\_driver\_init);
module\_exit(usb\_driver\_exit);
MODULE\_LICENSE("GPL");
usb\_driver.c
,编写 Makefile
并编译。sudo insmod usb\_driver.ko
dmesg
sudo rmmod usb\_driver
用于模拟键盘输入,可用于自动化测试、远程控制等场景。
使用 Linux 内核的输入子系统,通过 input\_dev
结构体来创建和注册输入设备。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/input.h>
static struct input\_dev \*my\_input\_dev;
static int \_\_init input\_driver\_init(void) {
int err;
my\_input\_dev = input\_allocate\_device();
if (!my\_input\_dev) {
printk(KERN\_ALERT "Failed to allocate input device.\n");
return -ENOMEM;
}
my\_input\_dev->name = "my\_keyboard";
set\_bit(EV\_KEY, my\_input\_dev->evbit);
set\_bit(KEY\_A, my\_input\_dev->keybit);
err = input\_register\_device(my\_input\_dev);
if (err) {
printk(KERN\_ALERT "Failed to register input device.\n");
input\_free\_device(my\_input\_dev);
return err;
}
input\_report\_key(my\_input\_dev, KEY\_A, 1);
input\_sync(my\_input\_dev);
input\_report\_key(my\_input\_dev, KEY\_A, 0);
input\_sync(my\_input\_dev);
printk(KERN\_INFO "Input device initialized and sent 'A' key event.\n");
return 0;
}
static void \_\_exit input\_driver\_exit(void) {
input\_unregister\_device(my\_input\_dev);
printk(KERN\_INFO "Input device removed.\n");
}
module\_init(input\_driver\_init);
module\_exit(input\_driver\_exit);
MODULE\_LICENSE("GPL");
input\_driver.c
,编写 Makefile
并编译。sudo insmod input\_driver.ko
sudo rmmod input\_driver
用于在屏幕上进行简单的图形显示,如嵌入式设备的小屏幕显示。
使用 Linux 内核的帧缓冲子系统,通过 fb\_info
结构体来实现帧缓冲设备驱动。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fb.h>
static struct fb\_info \*my\_fb\_info;
static int my\_fb\_set\_par(struct fb\_info \*info) {
return 0;
}
static int my\_fb\_blank(int blank, struct fb\_info \*info) {
return 0;
}
static struct fb\_ops my\_fb\_ops = {
.owner = THIS\_MODULE,
.fb\_set\_par = my\_fb\_set\_par,
.fb\_blank = my\_fb\_blank,
};
static int \_\_init fb\_driver\_init(void) {
my\_fb\_info = framebuffer\_alloc(0, NULL);
if (!my\_fb\_info) {
printk(KERN\_ALERT "Failed to allocate framebuffer info.\n");
return -ENOMEM;
}
my\_fb\_info->fbops = &my\_fb\_ops;
my\_fb\_info->var.xres = 640;
my\_fb\_info->var.yres = 480;
my\_fb\_info->var.bits\_per\_pixel = 16;
my\_fb\_info->fix.smem\_len = my\_fb\_info->var.xres \* my\_fb\_info->var.yres \*
(my\_fb\_info->var.bits\_per\_pixel / 8);
if (register\_framebuffer(my\_fb\_info)) {
printk(KERN\_ALERT "Failed to register framebuffer.\n");
framebuffer\_release(my\_fb\_info);
return -EFAULT;
}
printk(KERN\_INFO "Framebuffer device initialized.\n");
return 0;
}
static void \_\_exit fb\_driver\_exit(void) {
unregister\_framebuffer(my\_fb\_info);
framebuffer\_release(my\_fb\_info);
printk(KERN\_INFO "Framebuffer device removed.\n");
}
module\_init(fb\_driver\_init);
module\_exit(fb\_driver\_exit);
MODULE\_LICENSE("GPL");
fb\_driver.c
,编写 Makefile
并编译。sudo insmod fb\_driver.ko
fbset
命令查看帧缓冲设备信息:sudo fbset -i /dev/fbX # X 为帧缓冲设备编号
sudo rmmod fb\_driver
用于系统的硬件监控和故障恢复,当系统出现异常时,看门狗可以复位系统。
使用 Linux 内核的看门狗子系统,通过 watchdog\_device
结构体来实现看门狗设备驱动。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/watchdog.h>
static int my\_wdt\_start(struct watchdog\_device \*wdd) {
printk(KERN\_INFO "Watchdog started.\n");
return 0;
}
static int my\_wdt\_stop(struct watchdog\_device \*wdd) {
printk(KERN\_INFO "Watchdog stopped.\n");
return 0;
}
static int my\_wdt\_ping(struct watchdog\_device \*wdd) {
printk(KERN\_INFO "Watchdog pinged.\n");
return 0;
}
static struct watchdog\_info my\_wdt\_info = {
.options = WDIOF\_KEEPALIVEPING,
.firmware\_version = 1,
.identity = "My Watchdog",
};
static struct watchdog\_ops my\_wdt\_ops = {
.owner = THIS\_MODULE,
.start = my\_wdt\_start,
.stop = my\_wdt\_stop,
.ping = my\_wdt\_ping,
};
static struct watchdog\_device my\_wdt\_dev = {
.info = &my\_wdt\_info,
.ops = &my\_wdt\_ops,
};
static int \_\_init wdt\_driver\_init(void) {
return watchdog\_register\_device(&my\_wdt\_dev);
}
static void \_\_exit wdt\_driver\_exit(void) {
watchdog\_unregister\_device(&my\_wdt\_dev);
}
module\_init(wdt\_driver\_init);
module\_exit(wdt\_driver\_exit);
MODULE\_LICENSE("GPL");
wdt\_driver.c
,编写 Makefile
并编译。sudo insmod wdt\_driver.ko
watchdog
命令来操作看门狗设备:sudo echo 1 > /dev/watchdog # 启动看门狗
sudo echo V > /dev/watchdog # 停止看门狗
sudo rmmod wdt\_driver
以上是13个 Linux 驱动开发中常用的小案例,收藏起来,用得着的时候不会抓瞎,就像 V 哥经常会收集一些小案例在自己的知识库里,需要用的时候很方便可以检索到,你说用 AI?对 AI 很强大,但我自己调试好的小案例用起来也很方便,就像自己创建的一个智能体一样,你觉得呢。关注威哥爱编程,全栈开发就你行。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。