Linux驱动基础

lsmod显示模块:

lsmod 以美观的方式列出/proc/modules的内容。

输出为:

    Module(模块名)    Size(模块大小)   Used by(被...使用)

    在/proc/modules中相应的是:

    (模块名,模块大小,被...使用,模块地址

insmod:加载模块

rmmod:卸载模块

查看模块信息:

/proc/modules文件中列出了内核加载的所有模块的信息:

第一列:模块名称

第二列:模块使用的内存大小,单位是bytes

第三列:模块被load的次数

第四列:是否有其他模块依赖此模块,如果有,列出对应模块的名称

第五列:模块当前的状态,live(已经加载),loading(加载中),unloading(卸载中)

第六列:模块在内核内存中的偏移值

代码:

#include <linux/kernel.h>
#include <linux/module.h>  
#include <linux/fs.h>  
//#include <sys/types.h>
//#include <errno.h>
#include <linux/ioctl.h>  // 这个头文件可能定义了 unlocked_ioctl 的类型


#define MY_IOCTL_CMD 0x99
#define MY_IOCTL_TYPE 0x99

static int Major; // 主设备号  
static char msg[256]; // 存储消息的缓冲区  
static char *msg_Ptr; // 当前写入的位置  

void test(void)
{
    return ;
}
EXPORT_SYMBOL(test);

static int hello_open(struct inode *inode, struct file *file)  
{
    test();    
    return 0;  
}  
  
static int hello_read(struct file *filp, char *buffer, size_t length, loff_t * offset)  
{  
    int bytes_read = 0;  
    if (*msg_Ptr == 0) return 0; // 如果没有数据可读,返回0  
    while (length && *msg_Ptr) {  
        put_user(*(msg_Ptr++), buffer++); // 将数据复制到用户空间  
        length--;  
        bytes_read++;  
    }  
    return bytes_read;  
}  
  
static int hello_write(struct file *filp, const char *buff, size_t len, loff_t * off)  
{  
    int total_written = 0;  
    while (len) {  
        char c;  
        get_user(c, buff); // 从用户空间读取数据  
        *(msg_Ptr++) = c; // 将数据写入到消息缓冲区中  
        len--;  
        total_written++;  
        buff++;  
    }  
    return total_written;  
}  

static long hello_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  
{
      printk("hsm ioctl");
      if (_IOC_TYPE(cmd) != 0x99)
        return -ENOTTY;
      else
          printk("ok.......");
    
      return 0;
}

static int hello_release(struct inode *inode, struct file *file)  
{  
    msg_Ptr = msg; // 重置消息指针到开始位置,以便下一次写入可以从开始位置开始  
    return 0;  
}  

static struct file_operations hello_fops = {   
  //  .read = hello_read,    
  //  .write = hello_write,    
  //  .open = hello_open,    
  //  .release = hello_release,    
    .unlocked_ioctl = hello_ioctl, 
}; 

static int hello_init(void) {  
    Major = register_chrdev(0, "my_dev", &hello_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. To talk to the driver, create a dev file with 'mknod /dev/my_dev c %d 0'.\n", Major, Major);  
    return 0;  
}  
  
static void hello_exit(void) {  
    unregister_chrdev(Major, "my_dev");  
    printk(KERN_INFO "Unregistered and removed /dev/my_dev.\n");  
}  
  
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
 


Makefile:

obj-m := driver.o

KERNELDIR ?= /lib/modules/$(shell uname -r)/build
#KERNELDIR ?= /root/linux-4.19.90-all-arch-master
PWD       := $(shell pwd)

default:
    $(MAKE) -C ${KERNELDIR} M=$(PWD)  modules
clean:
    rm *.o *.ko *.symvers *.order *.mod.c .*.cmd .tmp_versions/ -rf

insmod后创建驱动文件,mknod /dev/my_dev c 237 0

应用:

#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#define MY_DEVICE_TYPE 0x99
#define MY_IOCTL_CMD  _IOWR (MY_DEVICE_TYPE, 0x99, unsigned long)

int main()
{
    int fd = open("/dev/my_dev", O_RDWR); // 替换为你的设备名  
    if (fd < 0) {  
        perror("open");  
        return -1;  
    }  
    if (ioctl(fd, MY_IOCTL_CMD, "hello") < 0) {  
        perror("ioctl");
        close(fd);  
        return -1;  
    }  
    printf("succ!\n");
    close(fd); // 别忘了关闭文件描述符!
    return -1;
}
 

        Makefile:

OBJ=app

$(OBJ): app.c
    gcc app.c -o app

.PHONY:clean

clean:
    rm -rf app
 

测试:

        

调用成功。

dmesg:

使用dmesg显示内核打印日志:

这样简单的驱动驱动程序就实现了。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值