0

私はこれが悪い考えであることを知っています!確かに、安全なプログラミングのために、特定のスレッドのスタックはそのスレッドに対してプライベートであると見なされるべきです。しかし、少なくとも POSIX は、スレッドのすべてのメモリが他のスレッドによって共有され、書き込み可能であることを保証します。これは、あるスレッドのスタックが (理論的には) 別のスレッドによって書き込まれる可能性があることを意味します。だから、どうやってそれができるのか興味があります。

私が考えることができる唯一の方法は、スレッド B のローカル変数のアドレスをスレッド A に渡し、A にその一般領域への書き込みを開始させることです。しかし、これは C での関数呼び出しを完全にエミュレートするものではありません。特に、プログラム カウンターがパラメーターを取る関数の最初の行に設定されている間、スレッド A をスリープ状態にしてから、スレッド B をスリープ状態にすることができるかどうかに興味があります。実際にそれらのパラメーターをスタックにプッシュしてから、スレッド A を再開し、スレッド A でそれらのパラメーターを使用して関数が最初に呼び出されたかのように実行します。これには、スレッド B が少なくとも x86 呼び出し規約の下でスレッド A のレジスタにアクセスできる必要があると思いますが、それが可能かどうかはわかりません。

4

3 に答える 3

2

スレッドのスタックにアクセスする 1 つの方法は、スタック メモリを自分で割り当て、スレッドの作成中に割り当てることです。これは、pthread_attr_setstack()呼び出しによって実現できます。

次のコードは、スレッド スタックをシステム割り当てではなく、手動で割り当てられたメモリ (ここでは malloc) に設定します。スレッドが作成されると、後で mystack ポインターにアクセスできます。このようなコードの使用例の 1 つは、スレッド スタックのダンプを取得してそのスナップショットを取得し、後でこのスレッドを復元できることです。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <limits.h>

   void *thread(void *arg) {
      char *ret;
      printf("thread() entered with argument '%s'\n", (char *)arg);
      if ((ret = (char*) malloc(20)) == NULL) {
        perror("malloc() error");
        exit(2);
      }
      strcpy(ret, "This is a test");
      pthread_exit(ret);
    }

    int main(void)
    {
       pthread_attr_t attr;
       int              rc;

      pthread_t thid;
      void *ret;

       void  *mystack;
       size_t mystacksize = 2 * PTHREAD_STACK_MIN;

       if (pthread_attr_init(&attr) == -1) {
          exit(1);
       }

       /* Get a big enough stack and align it on 4K boundary. */
       mystack = malloc(PTHREAD_STACK_MIN * 3);
       if (mystack != NULL) {
          printf("Using PTHREAD_STACK_MIN to align stackaddr %x.\n", mystack);
          mystack = (void *)((((long)mystack + (PTHREAD_STACK_MIN - 1)) /
                              PTHREAD_STACK_MIN) * PTHREAD_STACK_MIN);
       } else {
          exit(2);
       }

       printf("Setting stackaddr to %x\n", mystack);
       printf("Setting stacksize to %x\n", mystacksize);
       rc = pthread_attr_setstack(&attr, mystack, mystacksize);
       if (rc != 0) {
          printf("pthread_attr_setstack returned: %d\n", rc);
          exit(3);
       } else {
          printf("Set stackaddr to %x\n", mystack);
          printf("Set stacksize to %x\n", mystacksize);
       }


      if (pthread_create(&thid, &attr, thread, "thread 1") != 0) {
        exit(1);
      }

      if (pthread_join(thid, &ret) != 0) {
        exit(3);
      }

      printf("thread exited with '%s'\n", ret);
       rc = pthread_attr_destroy(&attr);
       if (rc != 0) {
          exit(5);
       }

       exit(0);
    }

これがあなたが望んでいたものかどうかお知らせください。インデントとコーディングスタイルが悪くてすみません。

于 2009-10-30T14:31:44.190 に答える
1

スレッド A のvolatile関数内のローカル変数へのポインターをスレッド B の関数に渡し、スレッド B にその内容を変更させるとうまくいく場合があります。foo()bar()

しかし、最適化とスレッド メモリ キャッシングに直面して、これが機能することを保証する方法はありません。

そうですね、これはおそらく悪い考えです。なぜこれをしたいのですか?セマフォまたはミューテックスはより良い解決策でしょうか?

于 2009-10-29T23:30:38.600 に答える
0

独自の (高速な) ユーザー空間ミューテックスを実装しようとしているようです。それらはトリッキーかもしれませんが、少なくとも (最後の手段として) レースを仲裁するためのカーネルが必要です。

Loadmasterが提案したことは、2 つのスレッドで機能する可能性があります2つ以上だと、非常に厄介になります。さらに、揮発性が常に揮発性であるとは限らないという彼の発言に賛成です。

于 2009-10-30T02:14:47.243 に答える