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

    曙海教育集團論壇Linux專區Linux驅動開發 → 深入淺出Linux設備驅動之并發控制(2)


      共有8874人關注過本帖樹形打印

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

    美女呀,離線,留言給我吧!
    wangxinxin
      1樓 個性首頁 | 博客 | 信息 | 搜索 | 郵箱 | 主頁 | UC


    加好友 發短信
    等級:青蜂俠 帖子:1393 積分:14038 威望:0 精華:0 注冊:2010-11-12 11:08:23
    深入淺出Linux設備驅動之并發控制(2)  發帖心情 Post By: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",如下圖:

    圖片點擊可在新窗口打開查看
    輸出結果

    支持(0中立(0反對(0單帖管理 | 引用 | 回復 回到頂部

    返回版面帖子列表

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








    簽名
    主站蜘蛛池模板: 日本韩国三级在线| 高h视频在线播放| 日韩成人国产精品视频| 全黄大全大色全免费大片| 18禁裸乳无遮挡啪啪无码免费 | 91精品国产乱码在线观看| 尤物网址在线观看日本| 五月婷婷中文字幕| 欧美日韩精品一区二区三区在线 | 99热在线精品免费播放6| 日本福利片国产午夜久久| 亚洲精品nv久久久久久久久久| 精品少妇人妻AV一区二区三区| 国产精品三级电影在线观看| 亚洲av无码久久精品蜜桃| 欧美精品无需播放器在线观看| 四虎影永久在线观看网址| 香蕉高清免费永久在线视频| 娇小性色xxxxx中文| 亚洲中文字幕无码久久| 欧美黄色大片免费观看| 啊灬啊别停灬用力视频啊视频| 麻豆精品视频入口| 天堂在线中文字幕| 亚洲中文字幕无码专区| 毛片基地看看成人免费| 国产18禁黄网站免费观看| 露暴的楠楠健身房单车| 国产精品福利电影| 一个人hd高清在线观看| 成人毛片免费视频播放| 久久精品女人的天堂AV| 极品美女aⅴ高清在线观看| 伊人一伊人色综合网| 精品亚洲aⅴ在线观看| 91精品欧美产品免费观看| 成人无码精品一区二区三区| 久操视频在线免费观看| 机巴太粗太硬弄死你| 亚洲欧美成人在线| 波多洁野衣一二区三区|