1. 程式人生 > 其它 >【專業技術】Linux裝置驅動第八篇:高階字元驅動操作之裝置存取控制

【專業技術】Linux裝置驅動第八篇:高階字元驅動操作之裝置存取控制

上一篇中介紹了阻塞IO等的一些用法,本來這一篇準備介紹一下poll/select等的一些高階IO操作,後來想想,在實際工作中開發驅動的時候很少會使用到poll/select這些操作,就不再介紹,有興趣的可以自己查詢資料學習一下。這一篇會介紹下相對比較實用的裝置檔案的存取控制的一些內容。

存取控制主要用於裝置的使用控制,只有授權的使用者才能訪問裝置或者同時只有一個程序訪問裝置。這也是存取控制使用最廣的地方。下面分別簡單說明。

單open裝置

單open裝置就是同時只有一個程序允許開啟一次所要訪問的裝置。此種方法是最簡單方便的訪問控制策略,可以防止多程序的競爭問題,但是這樣也造成了其侷限性。不能同時被多個程序多個使用者訪問。下面是一個單open裝置的簡單實現:

static atomic_t scull_s_available = ATOMIC_INIT(1);
static int scull_s_open(struct inode *inode, struct file *filp)
{

        struct scull_dev *dev = &scull_s_device; /* device information */
        if (! atomic_dec_and_test (&scull_s_available))
        {
                atomic_inc(&scull_s_available);
                return -EBUSY; /* already open */
        }

        /* then, everything else is copied from the bare scull device */
        if ( (filp->f_flags & O_ACCMODE) == O_WRONLY)

                scull_trim(dev);
        filp->private_data = dev;
        return 0; /* success */
}

這段程式碼維護一個 atiomic_t 變數,稱為 scull_s_available;這個變數被初始化為值 1,表示裝置確實可用。open 呼叫遞減並測試 scull_s_available 並拒絕存取如果其他人已經使裝置開啟。

release呼叫,標識裝置不再忙。

static int scull_s_release(struct inode *inode, struct file *filp)
{
        atomic_inc(&scull_s_available); /* release the device */
        return 0;
}

單使用者多程序使用裝置

這種方式更高階一些,可以允許單個使用者的多個程序同時使用裝置。這種方式在第一次開啟裝置是會記住裝置擁有著,當下一次同一個使用者開啟裝置時也會得到允許。在上面介紹的open實現中需要加入類似下面的程式碼:

spin_lock(&scull_u_lock);
if (scull_u_count &&
                (scull_u_owner != current->uid) && /* allow user */
                (scull_u_owner != current->euid) && /* allow whoever did su */
                !capable(CAP_DAC_OVERRIDE))
{ /* still allow root */
        spin_unlock(&scull_u_lock);
        return -EBUSY; /* -EPERM would confuse the user */
}

if (scull_u_count == 0)
        scull_u_owner = current->uid; /* grab it */

scull_u_count++;
spin_unlock(&scull_u_lock);

這裡有幾個注意點,scull_u_owner 和 scull_u_count來控制對裝置的存取,並且可被多個程序併發地存取,為了使這倆個變數安全,使用自旋鎖來控制。

返回-EBUSY而不是-EPERM,我們這種情況雖然看著是在檢查許可權,但如果返回-EPERM,使用者一般會去檢查裝置節點的檔案mode已經擁有著,這是一個錯誤的方向。所以返回裝置忙更合理。

相應的release方法如下:

static int scull_u_release(struct inode *inode, struct file *filp)
{
        spin_lock(&scull_u_lock);
        scull_u_count--; /* nothing else */
        spin_unlock(&scull_u_lock);
        return 0;
}

以上就是裝置存取控制最常用方法,還有一些不常用的點沒有仔細介紹。有興趣的可以自行了解,也歡迎隨時交流。