2015-08-08 24 views
4

我有一個程序有兩個與共享內存進行通信的進程。在ctrl-c我希望這兩個進程退出。我使用一個名爲stop的變量atomic_bool來通知進程保持循環或在設置爲true時退出。但是,當atomic_bool變量停止設置爲true時,其他進程看不到更改。意思是它仍然打印出0而不是1,但是進行更改的過程顯示爲1.那麼,爲什麼第二個過程看不到從假到真的變化?atomic_bool值更新,其他進程沒有看到

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; 
} 

回答

6

你傳遞你的原子變量的副本到您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; 
} 
0

下面的代碼是沒有「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; 
}