ホームページ  >  記事  >  バックエンド開発  >  Dia e - C のコンテキストを理解する

Dia e - C のコンテキストを理解する

Linda Hamilton
Linda Hamiltonオリジナル
2024-10-21 08:08:02358ブラウズ

Dia e - Entendendo contextos em C

C では、コンテキストとは、レジスタ (プログラム実行中にデータや命令を保存するために使用される CPU 内の小さな記憶領域)、変数、フローを含むプログラムの現在の実行状態です。タスクの切り替えに重要な命令。

オペレーティング システムのコンテキスト切り替え

主な機能はマルチタスクを可能にすることです。これにより、システムはプロセス間を効率的に切り替えることができます。

contexts.c ファイルはここから入手可能です。これは、コンテキストがどのように機能するかを示すデモです。

このファイルの先頭に、ucontext.h ライブラリのインポートがあることがわかります。これにより、実行コンテキストを操作できます。

以下の抜粋では、3 つのコンテキストが作成され、これらの 3 つのコンテキストには STACKSIZE のサイズのメモリが割り当てられることがわかります。

#define STACKSIZE 64 * 1024 /* tamanho de pilha das threads */

ucontext_t ContextPing, ContextPong, ContextMain;

そしてそのすぐ後に、それぞれのコンテキストで実行される Ping 関数と Pong 関数:

void BodyPing(void *arg)
{
  int i;

  printf("%s: inicio\n", (char *)arg);

  for (i = 0; i < 4; i++)
  {
    printf("%s: %d\n", (char *)arg, i);
    swapcontext(&ContextPing, &ContextPong);
  }
  printf("%s: fim\n", (char *)arg);

  swapcontext(&ContextPing, &ContextMain);
}

/*****************************************************/

void BodyPong(void *arg)
{
  int i;

  printf("%s: inicio\n", (char *)arg);

  for (i = 0; i < 4; i++)
  {
    printf("%s: %d\n", (char *)arg, i);
    swapcontext(&ContextPong, &ContextPing);
  }
  printf("%s: fim\n", (char *)arg);

  swapcontext(&ContextPong, &ContextMain);
}

/*****************************************************/

メイン関数では、malloc を使用してスタックを予約し、後で uc_stack.ss_sp を使用してスタックをコンテキストに割り当て、swapcontext を使用してスタックを切り替えます。

int main(int argc, char *argv[])
{
  char *stack;

  printf("main: inicio\n");

  getcontext(&ContextPing);

  stack = malloc(STACKSIZE);
  if (stack)
  {
    ContextPing.uc_stack.ss_sp = stack;
    ContextPing.uc_stack.ss_size = STACKSIZE;
    ContextPing.uc_stack.ss_flags = 0;
    ContextPing.uc_link = 0;
  }
  else
  {
    perror("Erro na criação da pilha: ");
    exit(1);
  }

  makecontext(&ContextPing, (void *)(*BodyPing), 1, "    Ping");

  getcontext(&ContextPong);

  stack = malloc(STACKSIZE);
  if (stack)
  {
    ContextPong.uc_stack.ss_sp = stack;
    ContextPong.uc_stack.ss_size = STACKSIZE;
    ContextPong.uc_stack.ss_flags = 0;
    ContextPong.uc_link = 0;
  }
  else
  {
    perror("Erro na criação da pilha: ");
    exit(1);
  }

  makecontext(&ContextPong, (void *)(*BodyPong), 1, "        Pong");

  swapcontext(&ContextMain, &ContextPing);
  swapcontext(&ContextMain, &ContextPong);

  printf("main: fim\n");

  exit(0);
}

実行されたプログラムの出力:

main: inicio
    Ping: inicio
    Ping: 0
        Pong: inicio
        Pong: 0
    Ping: 1
        Pong: 1
    Ping: 2
        Pong: 2
    Ping: 3
        Pong: 3
    Ping: fim
        Pong: fim
main: fim

これにより、コンテキストを変更した場合でも、関数を介して「流れる」値が維持されることがわかります。この場合の例は for インデックスです。

ピンとポンのコンテキストに malloc があることに気づいたかもしれませんが、main にもコンテキストがあることがわかります。なぜこれに malloc がないのですか?

ContextMain はメインスレッドのスタック上で動作するため、別個のスタックを必要としませんが、Ping および Pong コンテキストには動的に割り当てられた独自のスタックがあります。

コンテキストを作成してメモリを割り当てなかった場合、スワップを使用すると、コンテキストはプログラムのメイン スタックに移動します。

このコードは Maziero 教授からのもので、PingPongOS の開発されたサブプロジェクト「Trocas de Contexto」にあります。

以上がDia e - C のコンテキストを理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。