2015-08-08 57 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; 
}