如何创建一个简单的驱动程序? [求助]

时间:2017-11-11 16:21:49

标签: c linux-kernel driver ubuntu-16.04 kernel-module

我们的想法是创建一个可以通过设备进行通信的驱动程序和用户应用程序。

当我编译模块,将其附加到内核并创建设备时,我不会收到任何错误,但是当我启动用户应用程序时,它会崩溃。此外,崩溃后,我的电脑变慢,有时甚至我需要重新启动我的系统。 我也读过内核日志文件,发现了这个错误:[ 336.741386] BUG: unable to handle kernel NULL pointer dereference at (null)

如果我的代码出现问题,请告诉我吗?

驱动程序代码:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>           // Allows to open/read/write/execute a device
#include <linux/cdev.h>         // Char driver; makes cdev available
#include <linux/semaphore.h>    // Used to access semaphores; used for synchronization for avoiding crashes
#include <asm/uaccess.h>        // Copy_to_user;copy_from_user

struct fake_device{
    char data[100];
    struct semaphore sem;
}virtual_device;

struct cdev *mcdev;     // My Char device driver
int major_number;
int ret;

dev_t dev_num;

#define DEVICE_NAME "looperdevice"

int device_open(struct inode *inode, struct file *filp){
    if(down_interruptible(&virtual_device.sem) != 0){
        printk(KERN_ALERT "looperdevice: could not lock device during open");
        return -1;
    }
    printk(KERN_INFO "looperdevice: opened device");
    return 0;

}
ssize_t device_read(struct file* filp, char* bufStoreData, size_t bufCount, loff_t* curOffset){
    printk(KERN_INFO "looperdevice: Reading from device");
    ret = copy_to_user(bufStoreData, virtual_device.data, bufCount);
    return ret;
}

ssize_t device_write(struct file* filp, const char* bufSourceData, size_t bufCount, loff_t* curOffset){
    printk(KERN_INFO "looperdevice: Writing to device");
    ret = copy_from_user(virtual_device.data, bufSourceData, bufCount);
    return ret;
}

int device_close(struct inode *inode, struct file *filp){
    printk(KERN_INFO "looperdevice: Closing device");
    up(&virtual_device.sem); // Set semaphore up
    return 0;
}


struct file_operations fops = {
    .owner =    THIS_MODULE,
    .open = device_open,
    .release = device_close,
    .write = device_write,
    .read = device_read
};

static int driver_entry(void){
    /*
    Register our device in the system
    alloc_chrdev_region(dev_t*, uint fminor, uint count, char* name)
    */
    ret = alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME); // Will store minor and max number into dev_num, for future extraction
    if (ret < 0){
        printk(KERN_ALERT "looperdevice: failed to allocate a major number");
        return ret;
    }
    // Extracting major number
    major_number = MAJOR(dev_num);
    printk(KERN_INFO "looperdevice: major_number extracted, %d", major_number);
    printk(KERN_INFO "\tuse \"mknod /dev/%s c %d 0\" for device file",DEVICE_NAME, major_number);

    mcdev = cdev_alloc(); // Create our cdev structure already initializated
    mcdev->ops = &fops;     // struct file operations
    mcdev->owner = THIS_MODULE;
    // Now that we created the cdev we have to add it to the kernel
    // int cdev_add(struct cdev* dev, dev_t num, unsigned int count)
    ret = cdev_add(mcdev, dev_num, 1);
    if (ret < 0){
        printk(KERN_ALERT "looperdevice: unable to add cdev to kernel");
        return ret;

    }
    // Initialize our semaphore
    sema_init(&virtual_device.sem, 1);

    return 0;
}
static void driver_exit(void){
    cdev_del(mcdev);
    unregister_chrdev_region(dev_num,1);
    printk(KERN_ALERT "looperdevice: Unloaded module");

}

module_init(driver_entry);
module_exit(driver_exit);

用户应用程序代码:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

#define DEVICE "/dev/looperdevice"

int main(){
    int i, fd, ch;
    char write_buf[100], read_buf[100];
    fd = open(DEVICE, O_RDWR);
    if (fd == -1){
        printf("file %s either does not exist or has been locked by another process\n", DEVICE);
        exit(-1);
    }
    printf("Looper application v0.1 Beta\n");
    while (ch != 3){
        printf("--------------MENU-------------\n");
        printf("1. Read from device\n2. Write to device\n3. Exit");
        printf("Choose an option: ");
        scanf("%d", &ch);
        switch(ch){
            case 1:
                // reading from device
                read(fd, read_buf, sizeof(read_buf));
                printf("DEVICE: %s\n", read_buf);
                break;
            case 2:
                // Writing to device
                printf("Enter Data: ");
                gets(write_buf);
                write(fd, write_buf, sizeof(write_buf));
                break;
            case 3:
                exit(0);
                break;
            default:
                printf("Invalid option\n");
                break;
        }
    }
    return 0;
}

KERNEL日志文件:

[  321.242532] driver: module license 'unspecified' taints kernel.
[  321.242534] Disabling lock debugging due to kernel taint
[  321.243024] looperdevice: major_number extracted, 241
[  321.243026]  use "mknod /dev/looperdevice c 241 0" for device file
[  321.243028] looperdevice: unable to add cdev to kernel
[  336.741386] BUG: unable to handle kernel NULL pointer dereference at                                           (null)
[  336.741524] IP: __down_interruptible+0x51/0xf0
[  336.741563] PGD a3279067 
[  336.741564] PUD a3278067 
[  336.741589] PMD 0 

[  336.741650] Oops: 0002 [#1] SMP
[  336.741680] Modules linked in: driver(POE) ccm bnep pci_stub vboxpci(OE) vboxnetadp(OE) vboxnetflt(OE) vboxdrv(OE) dm_crypt dell_wmi sparse_keymap uvcvideo videobuf2_vmalloc videobuf2_memops videobuf2_v4l2 videobuf2_core videodev media dell_laptop dell_smbios btusb dcdbas btrtl btbcm btintel dell_smm_hwmon bluetooth arc4 iwldvm mac80211 intel_rapl x86_pkg_temp_thermal intel_powerclamp snd_hda_codec_hdmi coretemp kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel pcbc snd_hda_codec_idt snd_hda_codec_generic aesni_intel aes_x86_64 crypto_simd glue_helper cryptd intel_cstate intel_rapl_perf snd_hda_intel snd_hda_codec snd_hda_core snd_hwdep snd_pcm input_leds snd_seq_midi joydev snd_seq_midi_event serio_raw snd_rawmidi snd_seq binfmt_misc iwlwifi snd_seq_device snd_timer cfg80211
[  336.742291]  lpc_ich shpchp snd mei_me soundcore mei wmi dell_smo8800 mac_hid dell_rbtn parport_pc ppdev lp parport autofs4 hid_generic usbhid hid i915 ahci libahci psmouse i2c_algo_bit drm_kms_helper sdhci_pci sdhci syscopyarea sysfillrect e1000e sysimgblt fb_sys_fops drm ptp pps_core fjes video
[  336.742530] CPU: 2 PID: 3578 Comm: app Tainted: P           OE   4.10.0-37-generic #41~16.04.1-Ubuntu
[  336.742607] Hardware name: Dell Inc. Latitude E5430 vPro/0NVFXC, BIOS A16 08/19/2015
[  336.742673] task: ffff96ace1e08000 task.stack: ffffb4d500b68000
[  336.742727] RIP: 0010:__down_interruptible+0x51/0xf0
[  336.742771] RSP: 0018:ffffb4d500b6bba0 EFLAGS: 00010046
[  336.742817] RAX: 0000000000000000 RBX: ffffffffc0be84c8 RCX: 0000000000000002
[  336.742878] RDX: ffffffffc0be84d0 RSI: 0000000000000292 RDI: ffffffffc0be84c8
[  336.742938] RBP: ffffb4d500b6bbe8 R08: 0000000000000000 R09: 0000000000000000
[  336.742998] R10: 00000000000000f1 R11: ffff96acaa4d6338 R12: 7fffffffffffffff
[  336.743058] R13: ffff96ace1e08000 R14: ffff96ace294eb00 R15: ffffffffaf9c5c80
[  336.743120] FS:  00007fadeade0700(0000) GS:ffff96ad5e300000(0000) knlGS:0000000000000000
[  336.743188] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  336.743237] CR2: 0000000000000000 CR3: 00000000a337a000 CR4: 00000000001406e0
[  336.743298] Call Trace:
[  336.743329]  ? exact_lock+0x11/0x20
[  336.743363]  down_interruptible+0x4b/0x60
[  336.743403]  device_open+0x15/0x30 [driver]
[  336.743442]  chrdev_open+0xbf/0x1b0
[  336.743477]  do_dentry_open+0x208/0x310
[  336.743514]  ? cdev_put+0x30/0x30
[  336.743548]  vfs_open+0x4c/0x70
[  336.743581]  ? may_open+0x9b/0x100
[  336.743620]  path_openat+0x2ac/0x1430
[  336.743660]  ? page_add_file_rmap+0x58/0x140
[  336.743702]  do_filp_open+0x91/0x100
[  336.743738]  ? __alloc_fd+0x46/0x170
[  336.743774]  do_sys_open+0x12d/0x280
[  336.743809]  SyS_open+0x1e/0x20
[  336.743841]  entry_SYSCALL_64_fastpath+0x1e/0xad
[  336.743883] RIP: 0033:0x7fadea912010
[  336.743916] RSP: 002b:00007ffcf9ce3238 EFLAGS: 00000246 ORIG_RAX: 0000000000000002
[  336.743982] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fadea912010
[  336.744042] RDX: 00007ffcf9ce3428 RSI: 0000000000000002 RDI: 00000000004009b8
[  336.746348] RBP: 00007ffcf9ce3330 R08: 00000000004009a0 R09: 00007fadeabf5ab0
[  336.748583] R10: 000000000000069d R11: 0000000000000246 R12: 00000000004006b0
[  336.750831] R13: 00007ffcf9ce3410 R14: 0000000000000000 R15: 0000000000000000
[  336.753533] Code: 00 00 48 83 e4 f0 48 83 ec 30 65 48 8b 04 25 28 00 00 00 48 89 44 24 28 31 c0 48 8b 47 10 48 89 14 24 48 89 67 10 48 89 44 24 08 <48> 89 20 4c 89 6c 24 10 c6 44 24 18 00 eb 38 4d 85 e4 7e 52 49 
[  336.758651] RIP: __down_interruptible+0x51/0xf0 RSP: ffffb4d500b6bba0
[  336.761183] CR2: 0000000000000000
[  336.775501] ---[ end trace 3fcbe3000944b329 ]---

我希望你能帮助我:)。

1 个答案:

答案 0 :(得分:0)

解决方案是添加模块许可证:

MODULE_LICENSE("GPL");

谢谢:)