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

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


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

    主題:深入淺出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)








    簽名
    主站蜘蛛池模板: 正在播放国产伦理片| 80电影天堂网理论r片| 日韩精品一卡二卡三卡四卡2021| 再深点灬舒服灬太大了添动视频 | 亚洲欧洲国产经精品香蕉网| 精品伊人久久久久网站| 国产无遮挡又黄又爽网站| eeuss影院机在线播放| 性色生活片在线观看| 久草视频精品在线| 欧美三级不卡在线观看| 伊人久热这里只精品视频| 精品国自产拍天天拍2021| 国产女人高潮视频在线观看| 91麻豆爱豆果冻天美星空| 女人与拘做受AAAAA片| 久久久久久久岛国免费播放| 日韩人妻一区二区三区蜜桃视频| 亚洲欧美日韩中文字幕在线一 | 国产精品久久香蕉免费播放| www成人在线观看| 性做久久久久久| 久久国产色AV免费观看| 日韩男人的天堂| 国产一区二区久久精品| 含羞草实验研究所入口免费网站直接进入| 国产91精品一区二区视色 | 渣男渣女抹胸渣男渣女软件| 粗壮挺进人妻水蜜桃成熟漫画| 精品福利视频一区二区三区| 大黑人交xxxx| 久久99精品国产麻豆婷婷| 日韩精品无码人成视频手机 | 99久久免费精品国产72精品九九| 嫩b人妻精品一区二区三区| 久久亚洲AV成人无码| 91精品国产一区| 极品精品国产超清自在线观看| 人人玩人人添人人| 男女男精品网站| 国产MD视频一区二区三区|