【问题标题】:atomic_bool value update, not seen by other processesatomic_bool 值更新,其他进程看不到
【发布时间】:2015-08-08 22:38:24
【问题描述】:

我有一个程序,它有两个与共享内存通信的进程。在 ctrl-c 上,我希望两个进程都退出。我正在使用一个名为 stop 的 atomic_bool 变量来通知进程在设置为 true 时保持循环或退出。但是,当 atomic_bool 变量 stop 设置为 true 时,其他进程看不到更改。这意味着它仍然打印出 0 而不是 1,但是进行更改的进程显示 1。那么为什么第二个进程没有看到从 false 到 true 的更改?

Control-c 不能杀死进程,所以请改用killall。

#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <stdbool.h>
#include <stdatomic.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <errno.h>

struct shared_map
{

    atomic_bool stop;

};

struct shared_map *map;

int compare_and_swap_loop(atomic_bool target, int value)
{
    /* Loop until we can succesfully update the the value. */
    while(1)
    {
        /* Grab a snapshot of the value that need to be updated. */
        bool snapshot = atomic_load(&target);

        if(atomic_compare_exchange_weak(&target, &snapshot, value) == true)
        {
            /* We succesfully updated the value let's exit this loop and return. */
            break;
        }
    }

   printf("result: %d\n", atomic_load(&target));

    return 0;
}

static void ctrlc_handler(int sig)
{
    compare_and_swap_loop(&map->stop, true);

    return;
}

void setup_signal_handler(void)
{
    (void) signal(SIGINT, ctrlc_handler);

    return;
}

static int create_shared(void **pointer, int size)
{
    *pointer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
    if(*pointer == MAP_FAILED)
    {
        printf("mmap: %s\n", strerror(errno));
        return -1;
    }

    return 0;
}

static void loop(void)
{
    /* Set up signal handler. */
    setup_signal_handler();

    /* Check if we should stop or continue running. */
    while(atomic_load(&map->stop) == false)
    {
        sleep(2);

        printf("map->stop: %d\n", atomic_load(&map->stop));
    }

    return;
}

int main(void)
{
    int rtrn;
    pid_t pid;

    rtrn = create_shared((void **)&map, sizeof(struct shared_map));
    if(rtrn < 0)
    {
        printf("Can't create shared memory\n");
        return -1;
    }

    atomic_init(&map->stop, false);

    pid = fork();
    if(pid == 0)
    {
        loop();

        _exit(0);
    }
    else if(pid > 0)
    {
        int status;

        waitpid(pid, &status, 0);

        return 0;
    }
    else
    {
        printf("fork: %s\n", strerror(errno));
        return -1;
    }

    return 0;
}

【问题讨论】:

    标签: c struct c11


    【解决方案1】:

    您将原子变量的副本传递给您的 compare_and_swap_loop 函数,这对您没有任何好处 - 您需要处理在进程之间共享的相同值。

    你需要这样做:

    int compare_and_swap_loop(atomic_bool *target, int value)
    {
       /* Loop until we can succesfully update the the value. */
       while(1)
       {
        /* Grab a snapshot of the value that need to be updated. */
           bool snapshot = atomic_load(target);
    
           if(atomic_compare_exchange_weak(target, &snapshot, value) == true)
           {
            /* We succesfully updated the value let's exit this loop and return. */
            break;
           }
       }
    
       printf("result: %d\n", atomic_load(target));
    
       return 0;
    }
    

    【讨论】:

      【解决方案2】:

      以下代码是在没有“atomic_*”命令的情况下编写的 但确实显示了您的流程有什么不正确的地方。

      大多数情况下,需要杀死子 pid,而不是父 pid

      下面的代码显示了子pid,所以很容易找到

      #define _GNU_SOURCE
      
      #include <string.h>
      #include <unistd.h>
      #include <stdio.h>
      #include <signal.h>
      #include <stdbool.h>
      //#include <stdatomic.h>
      #include <sys/mman.h>
      #include <sys/wait.h>
      #include <sys/types.h>
      #include <errno.h>
      
      struct shared_map
      {
          bool stop;
      };
      
      struct shared_map *map;
      
      int compare_and_swap_loop( bool *target )
      {
          /* Loop until we can succesfully update the the value. */
          while(1)
          {
              /* Grab a snapshot of the value that need to be updated. */
              bool snapshot = *target;
      
              if(snapshot)
              {
                  /* We succesfully updated the value let's exit this loop and return. */
                  break;
              }
          }
      
          return 0;
      }
      
      static void ctrlc_handler(int sig)
      {
          if( SIGINT==sig)
          compare_and_swap_loop(&map->stop);
      
          return;
      }
      
      void setup_signal_handler(void)
      {
          (void) signal(SIGINT, ctrlc_handler);
      
          return;
      }
      
      static int create_shared(void **pointer, size_t size)
      {
          *pointer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
          if(*pointer == MAP_FAILED)
          {
              perror("mmap failed");
              return -1;
          }
      
          return 0;
      }
      
      static void loop(void)
      {
          /* Set up signal handler. */
          setup_signal_handler();
      
          /* Check if we should stop or continue running. */
          while(!map->stop)
          {
              sleep(2);
      
              printf("map->stop: %d\n", map->stop);
          }
      
          return;
      }
      
      int main(void)
      {
          int rtrn;
          pid_t pid;
      
          printf( "entered Main\n");
      
          rtrn = create_shared((void **)&map, sizeof(struct shared_map));
          if(rtrn < 0)
          {
              printf("Can't create shared memory\n");
              return -1;
          }
      
          map->stop = false;
      
          pid = fork();
          if(pid == 0)
          { //then child
              printf( "child process\n");
              loop();
      
              _exit(0);
          }
          else if(pid > 0)
          { // then parent
              int status;
              printf( "parent process\n");
              printf( "child Pid: %d\n", pid);
      
              waitpid(pid, &status, 0);
      
              return 0;
          }
          else
          { // else, fork failed
              perror("fork failed");
              return -1;
          }
      
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        相关资源
        最近更新 更多