【问题标题】:Modify global variable from child process in Linux在 Linux 中从子进程修改全局变量
【发布时间】:2011-02-21 01:53:30
【问题描述】:

我来自 C# 背景,在 C 语言的并发方面遇到了一些困难。我不会对你撒谎……这是我必须为学校做的项目的一部分。尽管我在专业上使用过高级语言,但我的高级论文教授强迫整个班级用 C 编写代码(我们大多数人几乎没有甚至没有经验... :( )。

不管怎样,回到问题上来。我有一个全局整数变量(从 0 开始),需要同时递增 5 个进程,直到达到 100(而不是 100%)。

基本上发生的事情是,每个子进程不是单独修改completionCounter,而是复制它......

是否有 lock(object) 或 C# 中可用的类似名称?我尝试使用二进制信号量,但我无法让它工作,我还没有玩过共享内存。

const int THREADCOUNT = 5;
int completionCounter = 0;

int main(int argc, char **argv)
{
    int count = 0;
    pid_t pid;    

    for(count = 0; count<THREADCOUNT; count++)
    {
        if( (pid = fork()) < 0 )
        {
            //error...
            return -1;
        }
        else if( pid == 0 )
        {
            //child;
            while(completionCounter != 100 )
            {
                printf("[%i] process downloading data chunk...", getpid());

                //do stuff here

                completionCounter += 5;

            }
        }
        else
        {
            //parent.
        }
    }    
}

【问题讨论】:

  • fork() 创建一个新进程,而不是线程——这就是他们创建值副本的原因。编辑:我要做的方式是创建一个“服务器”进程,有 5 个子“工作”进程,它们与管道通信 gnu.org/s/libc/manual/html_node/Creating-a-Pipe.html
  • @Rob 如果我要使用分叉,我将如何强制每个子进程修改全局值而不是复制它?

标签: c concurrency


【解决方案1】:

子进程不与其父进程共享变量。使用分叉子进程执行此操作的唯一方法是专门创建和映射共享内存以保存该值。

执行此操作的更合理方法是使用线程而不是子进程,但您似乎被分配的任务卡住了。在这种情况下,我会推荐类似的东西:

int *x = mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);

在分叉之前,然后在子进程中递增*x...

但是!

现在您必须处理同步问题。按原样,您很容易在输出中丢失或重复数字。查找 POSIX 进程共享互斥锁,让您开始朝那个方向前进...

【讨论】:

  • 我们实际上并不知道 OP 被分配了什么任务。我看不出有任何理由认为教授要求项目使用 fork。
  • @Jim:OP 说“我有一个全局整数变量(从 0 开始),需要同时递增 5 个进程,直到达到 100”。线程不是进程。当然也有可能是 OP 或者导师不理解这个……
  • OP 写道“这是我必须为学校做的项目的一部分。”不能假设 OP 的“问题”是由教授分配的——这似乎是 OP 已经确定的一些子问题,但这可能是基于错误的设计。请注意,讲师是 OP 的“高级论文教授”——那个和“项目”提出的建议比 OP 的问题陈述要先进得多。
  • @Jim:好的,我同意你的推理,同时我认为如果它是正确的,那么 OP 的问题措辞非常糟糕。
【解决方案2】:

你说的很对,你想要的可以用信号量来实现。试试man 3 sem_wait,那里有一个例子。

【讨论】:

  • 是的,但是如何获得信号量的实例?当您调用semget() 时,您只会得到一个整数信号量标识符。我不能用信号量做到这一点的原因是我无法获得信号量值。即使是获取值的函数也需要一个我不知道如何获取的sem_t 对象?
  • @bleepzter,Semaphore 用于保护多线程环境下对某些代码的访问。您可以使用共享内存来存储您的值和信号量(或 pthreads 互斥锁,如果您使用线程)来保护它。
【解决方案3】:

这不是由争用问题引起的,而是在创建新进程时(使用fork 时会发生这种情况),会创建内存空间的新副本。这实际上意味着您正在创建 5 个completionCounters - 每个进程一个。如果您希望所有内容共享相同的内存空间,请考虑使用 pthreads

【讨论】:

    猜你喜欢
    • 2012-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-14
    • 2022-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多