access_ok
が成功したにもかかわらず、__put_user
が例外を引き起こすように、次のコード(read
charドライバの実装)では、wait_event_interruptible
の間にMMU TLBエントリが変更される可能性がありますか?Linuxカーネル、ユーザ空間のバッファ、access_okを実行して待機して競合状態を作成しますか?
ユーザバッファをロックして、リクエストの間有効であるようにすることはできますか?
access_ok
のチェックを繰り返したら、wait_event_interruptible
の返品は安全ですか?
ssize_t mydriver_pkt_read(struct file* filp, char __user* const buff, size_t count, loff_t* offp)
{
struct mydriver_pkt_private* priv;
volatile unsigned short* iobase;
unsigned next;
char __user* p = buff;
if (count <= 0) return -EINVAL;
if (!access_ok(VERIFY_WRITE, buff, count)) return -EFAULT;
priv = (struct mydriver_pkt_private*)filp->private_data;
iobase = priv->iobase;
next = priv->retained;
if ((next & PKTBUF_FLAG_NOTEMPTY) == 0) {
next = ioread16(iobase);
if ((next & PKTBUF_FLAG_NOTEMPTY) == 0) { // no data, start blocking read
iowrite16(1, iobase); // enable interrupts
if (wait_event_interruptible(priv->wait_for_ringbuffer, (priv->retained & PKTBUF_FLAG_NOTEMPTY)))
return -ERESTARTSYS;
next = priv->retained;
}
}
while (count > 0) {
__put_user((char)next, p);
p++;
count--;
next = ioread16(iobase);
if ((next & PKTBUF_FLAG_STARTPKT) || !(next & PKTBUF_FLAG_NOTEMPTY)) {
priv->retained = next;
return (p - buff);
}
}
/* discard remainder of packet */
do {
next = ioread16(iobase);
} while ((next & PKTBUF_FLAG_NOTEMPTY) && !(next & PKTBUF_FLAG_STARTPKT));
priv->retained = next;
return (p - buff);
}
独占オープンコード:
int mydriver_pkt_open(struct inode* inode, struct file* filp)
{
struct mydriver_pkt_private* priv;
priv = container_of(inode->i_cdev, struct mydriver_pkt_private, cdevnode);
if (atomic_cmpxchg(&priv->inuse, 0, 1))
return -EBUSY;
nonseekable_open(inode, filp);
filp->private_data = priv;
return 0;
}
ところで、ドライバをセマフォで保護したい場合があります。 2つのプロセスが1回の読み取りで競合するとどうなりますか?それは、私が彼らがデバイス側の割り込みを無効にしてスリープ状態にするような方法で競争できるように私に見える... – bdonlan
@bdonlan:これは組み込みシステムです:1つのプロセッサ、1つのハードウェアスレッド。また、デバイスのインスタンスは1つしかありません(オープン時に実行、編集を参照)。私は 'fork'やスレッドを使って同時にリクエストを得ることは可能だと思いますが、ユーザモードのアプリケーションはマルチスレッドではありません。私はおそらくそれをどうにかスレッドセーフにする必要があります。 –
ああ、排他的に開いていれば、それは問題ではないと思います。 – bdonlan