<dfn id="is4kg"></dfn>
  • <ul id="is4kg"></ul>
  • <abbr id="is4kg"></abbr>
  • <ul id="is4kg"></ul>
    <bdo id="is4kg"></bdo>

    Rss & SiteMap

    曙海教育集團論壇 http://www.bjzhda.cn

    曙海教育集團論壇
    共1 條記錄, 每頁顯示 10 條, 頁簽: [1]
    [瀏覽完整版]

    標題:深入淺出Linux設備驅動之并發控制(2)

    1樓
    wangxinxin 發表于:2010-11-24 11:46:56
    下面進入對并發控制的實戰。首先,在globalvar的驅動程序中,我們可以通過信號量來控制對int global_var的并發訪問,下面給出源代碼:

    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/fs.h>
    #include <asm/uaccess.h>
    #include <asm/semaphore.h>
    MODULE_LICENSE("GPL");

    #define MAJOR_NUM 254

    static ssize_t globalvar_read(struct file *, char *, size_t, loff_t*);
    static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*);

    struct file_operations globalvar_fops =
    {
     read: globalvar_read, write: globalvar_write,
    };
    static int global_var = 0;
    static struct semaphore sem;

    static int __init globalvar_init(void)
    {
     int ret;
     ret = register_chrdev(MAJOR_NUM, "globalvar", &globalvar_fops);
     if (ret)
     {
      printk("globalvar register failure");
     }
     else
     {
      printk("globalvar register success");
      init_MUTEX(&sem);
     }
     return ret;
    }

    static void __exit globalvar_exit(void)
    {
     int ret;
     ret = unregister_chrdev(MAJOR_NUM, "globalvar");
     if (ret)
     {
      printk("globalvar unregister failure");
     }
     else
     {
      printk("globalvar unregister success");
     }
    }

    static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)
    {
     //獲得信號量
     if (down_interruptible(&sem))
     {
      return - ERESTARTSYS;
     }

     //將global_var從內核空間復制到用戶空間
     if (copy_to_user(buf, &global_var, sizeof(int)))
     {
      up(&sem);
      return - EFAULT;
     }

     //釋放信號量
     up(&sem);

     return sizeof(int);
    }

    ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)
    {
     //獲得信號量
     if (down_interruptible(&sem))
     {
      return - ERESTARTSYS;
     }

     //將用戶空間的數據復制到內核空間的global_var
     if (copy_from_user(&global_var, buf, sizeof(int)))
     {
      up(&sem);
      return - EFAULT;
     }

     //釋放信號量
     up(&sem);
     return sizeof(int);
    }

    module_init(globalvar_init);
    module_exit(globalvar_exit);

      接下來,我們給globalvar的驅動程序增加open()和release()函數,并在其中借助自旋鎖來保護對全局變量int globalvar_count(記錄打開設備的進程數)的訪問來實現設備只能被一個進程打開(必須確保globalvar_count最多只能為1):

    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/fs.h>
    #include <asm/uaccess.h>
    #include <asm/semaphore.h>

    MODULE_LICENSE("GPL");

    #define MAJOR_NUM 254

    static ssize_t globalvar_read(struct file *, char *, size_t, loff_t*);
    static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*);
    static int globalvar_open(struct inode *inode, struct file *filp);
    static int globalvar_release(struct inode *inode, struct file *filp);

    struct file_operations globalvar_fops =
    {
     read: globalvar_read, write: globalvar_write, open: globalvar_open, release:
    globalvar_release,
    };

    static int global_var = 0;
    static int globalvar_count = 0;
    static struct semaphore sem;
    static spinlock_t spin = SPIN_LOCK_UNLOCKED;

    static int __init globalvar_init(void)
    {
     int ret;
     ret = register_chrdev(MAJOR_NUM, "globalvar", &globalvar_fops);
     if (ret)
     {
      printk("globalvar register failure");
     }
     else
     {
      printk("globalvar register success");
      init_MUTEX(&sem);
     }
     return ret;
    }

    static void __exit globalvar_exit(void)
    {
     int ret;
     ret = unregister_chrdev(MAJOR_NUM, "globalvar");
     if (ret)
     {
      printk("globalvar unregister failure");
     }
     else
     {
      printk("globalvar unregister success");
     }
    }

    static int globalvar_open(struct inode *inode, struct file *filp)
    {
     //獲得自選鎖
     spin_lock(&spin);

     //臨界資源訪問
     if (globalvar_count)
     {
      spin_unlock(&spin);
      return - EBUSY;
     }
     globalvar_count++;

     //釋放自選鎖
     spin_unlock(&spin);
     return 0;
    }

    static int globalvar_release(struct inode *inode, struct file *filp)
    {
     globalvar_count--;
     return 0;
    }

    static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t
    *off)
    {
     if (down_interruptible(&sem))
     {
      return - ERESTARTSYS;
     }
     if (copy_to_user(buf, &global_var, sizeof(int)))
     {
      up(&sem);
      return - EFAULT;
     }
     up(&sem);
     return sizeof(int);
    }

    static ssize_t globalvar_write(struct file *filp, const char *buf, size_t len,
    loff_t *off)
    {
     if (down_interruptible(&sem))
     {
      return - ERESTARTSYS;
     }
     if (copy_from_user(&global_var, buf, sizeof(int)))
     {
      up(&sem);
      return - EFAULT;
     }
     up(&sem);
     return sizeof(int);
    }

    module_init(globalvar_init);
    module_exit(globalvar_exit);

      為了上述驅動程序的效果,我們啟動兩個進程分別打開/dev/globalvar。在兩個終端中調用./globalvartest.o測試程序,當一個進程打開/dev/globalvar后,另外一個進程將打開失敗,輸出"device open failure",如下圖:

    圖片點擊可在新窗口打開查看
    輸出結果
    共1 條記錄, 每頁顯示 10 條, 頁簽: [1]

    Copyright © 2000 - 2009 曙海教育集團
    Powered By 曙海教育集團 Version 2.2
    Processed in .03125 s, 2 queries.
    主站蜘蛛池模板: 久久91精品国产91久| 啊灬啊别停灬用力啊岳| 一二三四视频免费视频| 日韩a在线观看| 他强行给我开了苞| 羞羞视频在线播放| 国产精品情侣呻吟对白视频| 中文字幕julia中文字幕| 日韩精品电影一区亚洲| 伊人色综合久久天天| 老司机深夜福利视频| 国产精品久久久久三级| youjizz护士| 日本电影痴汉电车| 亚洲第一视频网站| 福利视频免费看| 国产剧情一区二区| 91九色视频在线观看| 天堂网2018| 中文字幕视频在线播放| 日韩污视频在线观看| 亚洲精品无码不卡在线播放| 精品一区二区91| 国产免费看插插插视频| 888午夜不卡理论久久| 天天干天天色综合| 久99久无码精品视频免费播放| 日韩高清一区二区三区不卡| 亚洲综合免费视频| 男女久久久国产一区二区三区| 国产国产人免费视频成69大陆| 91亚洲欧美综合高清在线| 女人十八黄毛片| 久久大香香蕉国产| 校园春色亚洲欧美| 亚洲精品国产精品乱码不卡√| 男人的j插入女人的p| 国产91青青成人a在线| 草莓黄色app| 国产成熟女人性满足视频| 91香蕉视频成人|