2017-11-11 259 views
-2

這個想法是創建一個可以通過設備進行通信的驅動程序和用戶應用程序。如何創建一個簡單的驅動程序? [Ubuntu]

當我編譯模塊時,將它附加到內核並創建設備,我沒有得到任何錯誤,但是當我啓動用戶應用程序時,它崩潰了。另外,在崩潰之後,我的電腦變慢了,有時甚至需要重啓我的系統。 我也讀過內核日誌文件,發現這個錯誤:[ 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; 
} 

內核日誌文件:

[ 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

'當我編譯模塊,將其連接到內核和創建設備,我沒有得到任何error' - 根據日誌,你**將模塊加載到內核時出現錯誤**:'looperdevice:無法將cdev添加到內核'。根據驅動程序的代碼,模塊的加載應該被取消(因爲返回負值),所以進一步的「BUG」看起來可疑。 – Tsyvarev

回答

0

解決方案是添加模塊蝨子NSE:

MODULE_LICENSE("GPL"); 

謝謝:)