0

すべて〜!

Linuxシステムには、相互排除すべき共有データがあります。そして、そのデータは、mmap によってカーネル空間とユーザー空間の間で共有されます。ということで、以下のようにプログラムしました。

/////////////ユーザースペース

void access_shared_data_user(void)
{
 //snip..
 ioctl(test_fd, IOCTL_DOWN_SEM);
 shared_data++;
 //some access to shared_data
 ioctl(test_fd, IOCTL_UP_SEM);
}<

/////////////カーネルスペース

static DEFINE_SEMAPHORE(test_sem);

static long test_ioctl(struct file *file, unsigned int cmd, unsigned long arg)<br>
{
 //snip..
 switch(cmd)
 {
    case IOCTL_DOWN_SEM:
      down(&test_sem);
    break;
    case IOCTL_UP_SEM:
      up(&test_sem);
    break;
    //snip..
}

void access_shared_data_kernel(void)
{
  //snip..
  down(&test_sem);
  shared_data++;
  //some access to shared_data
  up(&test_sem);
}

上記のプログラムは期待どおりに機能し、共有データは多くのスレッドから保護されていました。

ところで、上記のプログラムには問題があります。access_shared_data_kernel が IRQ ハンドラーなどのアトミック コンテキストで呼び出されると、セマフォがスリープ待機メソッドを使用するため、このプログラムでデッドロックが発生する可能性があります。

そこで、spinlock(spin_lock_irqsave) を使用しようとしましたが、ユーザー空間でスピンロックを使用する方法はないようです。

質問: アトミック コンテキストでユーザーとカーネルの間でデータを共有するソリューションはありますか?

4

2 に答える 2

2

単一の整数型の値をインクリメントまたはデクリメントするか、簡単に変更するだけの場合は、ロックされた操作を使用できます。atomic_tカーネルで使用するとうまく機能し、ユーザー モード アプリケーションではatmoic ビルトインを使用できます。

明らかに、文字列内の「すべての A を B に置き換える」などのより複雑なことを行う必要がある場合strcpy、バイナリ ツリーまたは「単一の操作にするのは簡単ではない」他の作業を変更する場合、解決策は次のとおりです。セマフォを使用します。しかし、あなたが言うように、それは IRQ (またはスケジューラーが「ロック」されている他の状況) からは機能しません。

さらに、「ユーザーモードがツリーのバランスを再調整するのをIRQで待つ」ことは本当にしたくありません。

IRQ からこれを修正する簡単な解決策はないと思います - 基本的に、そうすべきではありません。IRQ で使用できますdown_trylock。これにより、IRQ がスリープ状態になることはありません。セマフォが使用できない場合、ロックの取得に成功した場合は 0 を返し、ロックが他の何かによって既に保持されている場合はゼロ以外を返します。

さて、もちろん、「ロックが利用できない場合はどうすればよいか」というトリッキーな部分があります-そして、私はあなたの特定のケースに対して適切な答えを出すことはできません. 一般的な解決策は、ワークアイテムをキューに入れ、後で処理することです。

編集:「作業項目をキューに入れ、後で処理する」を実行する標準的な方法は、tasklet

于 2013-09-06T13:39:37.727 に答える
0


マッツ様

ご回答ありがとうございます。
プログラムを修正するには、 down_trylock が最適なソリューションだと思います。

実際には、atomic conterxt を呼び出した場合に、access_shared_data_kernel 関数で無条件に失敗を返すようにしました。
しかし、down_trylock を使用すると、無条件復帰である必要がなくなり、より効率的になります。

そこで、以下のようにコードを修正しました。
void access_shared_data_kernel(void)
{
//中略..
if(down_trylock(&mmclog_sem)){
if(in_atomic() || in_interrupt() || irqs_disabled()){
printk("アトミックコンテキストでセマフォの取得に失敗..!\ n");
-1 を返します。
}
そうでなければ
ダウン(&mmclog_sem);
}
共有データ++;
//shared_data への何らかのアクセス
up(&test_sem);
}

ありがとう、マッツ、

于 2013-09-09T02:21:45.147 に答える