C 原子布尔值更新,其他进程看不到
我有一个带有两个进程的程序,它们与共享内存通信。在ctrl-c上,我希望两个进程都退出。我正在使用一个名为stop的C 原子布尔值更新,其他进程看不到,c,struct,c11,C,Struct,C11,我有一个带有两个进程的程序,它们与共享内存通信。在ctrl-c上,我希望两个进程都退出。我正在使用一个名为stop的原子布尔变量通知进程在设置为true时保持循环或退出。但是,当atomic\u bool变量stop设置为true时,其他进程看不到更改。这意味着它仍然打印出0而不是1,但进行更改的过程显示为1。那么为什么第二个过程看不到从false到true的变化呢 Control-c无法终止进程,因此请改用killall #include <string.h> #include &
原子布尔
变量通知进程在设置为true时保持循环或退出。但是,当atomic\u 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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
结构共享映射
{
原子波停止;
};
结构共享图*map;
int比较和交换循环(原子布尔目标,int值)
{
/*循环,直到我们可以成功地更新值*/
而(1)
{
/*抓取需要更新的值的快照*/
bool snapshot=原子加载(&target);
if(原子比较交换弱(&target,&snapshot,value)==true)
{
/*我们成功地更新了值,让我们退出这个循环并返回*/
打破
}
}
printf(“结果:%d\n”,原子加载(&target));
返回0;
}
静态无效ctrlc_处理器(int sig)
{
比较\u和\u交换\u循环(&map->stop,true);
返回;
}
无效设置\信号\处理程序(无效)
{
(无效)信号(SIGINT、ctrlc_处理器);
返回;
}
静态整数创建共享(无效**指针,整数大小)
{
*指针=mmap(NULL,大小,保护读取,保护写入,映射非共享,-1,0);
如果(*指针==映射_失败)
{
printf(“mmap:%s\n”,strerror(errno));
返回-1;
}
返回0;
}
静态空心环(空心环)
{
/*设置信号处理器*/
设置信号处理程序();
/*检查是否应该停止或继续运行*/
while(原子加载(&map->stop)=false)
{
睡眠(2);
printf(“映射->停止:%d\n”,原子加载(&映射->停止));
}
返回;
}
内部主(空)
{
int rtrn;
pid_t pid;
rtrn=create_shared((void**)和map,sizeof(struct shared_map));
if(rtrn<0)
{
printf(“无法创建共享内存\n”);
返回-1;
}
原子初始化(&map->stop,false);
pid=fork();
如果(pid==0)
{
loop();
_出口(0);
}
否则,如果(pid>0)
{
智力状态;
waitpid(pid和status,0);
返回0;
}
其他的
{
printf(“fork:%s\n”,strerror(errno));
返回-1;
}
返回0;
}
您正在将原子变量的副本传递给比较和交换循环
函数,这对您没有任何好处-您需要处理进程之间共享的相同值
您需要这样做:
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;
}
下面的代码是在没有“atomic_u*”命令的情况下编写的 但这确实表明了您的流程中有哪些地方不正确 大多数情况下,需要杀死子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;
}
定义GNU源
#包括
#包括
#包括
#包括
#包括
//#包括
#包括
#包括
#包括
#包括
结构共享映射
{
布尔停止;
};
结构共享图*map;
整数比较和交换循环(布尔*目标)
{
/*循环,直到我们可以成功地更新值*/
而(1)
{
/*抓取需要更新的值的快照*/
bool snapshot=*目标;
如果(快照)
{
/*我们成功地更新了值,让我们退出这个循环并返回*/
打破
}
}
返回0;
}
静态无效ctrlc_处理器(int sig)
{
如果(SIGINT==sig)
比较\u和\u交换\u循环(&map->stop);
返回;
}
无效设置\信号\处理程序(无效)
{
(无效)信号(SIGINT、ctrlc_处理器);
返回;
}
静态int创建共享(无效**指针,大小\u t大小)
{
*指针=mmap(NULL,大小,保护读取,保护写入,映射非共享,-1,0);
如果(*指针==映射_失败)
{
perror(“mmap失败”);
返回-1;
}
返回0;
}
静态空心环(空心环)
{
/*设置信号处理器*/
设置信号处理程序();
/*检查是否应该停止或继续运行*/
同时(!映射->停止)
{
睡眠(2);
printf(“映射->停止:%d\n”,映射->停止);
}
返回;
}
内部主(空)
{
int rtrn;
pid_t pid;
printf(“输入的主\n”);
rtrn=create_shared((void**)和map,sizeof(struct shared_map));
if(rtrn<0)
{
printf(“无法创建共享内存\n”);
返回-1;
}
map->stop=false;
pid=fork();
如果(pid==0)
{//然后是孩子
printf(“子进程”);
loop();
_出口(0);
}
否则,如果(pid>0)
{//然后是家长
智力状态;
printf(“父进程”);
printf(“子Pid:%d\n”,Pid);
waitpid(pid和status,0);
返回0;
}
其他的
{//否则,fork失败
perror(“fork失败”);
返回-1;
}
返回0;
}