确保两个进程交错

发布于 2024-11-05 13:25:27 字数 1139 浏览 0 评论 0原文

在 Linux 上的 C 程序中,我使用 fork() 和 execve() 两次来创建运行两个单独程序的两个进程。如何确保两个子进程交错执行? 谢谢 尝试按照下面给出的答案执行上述任务,但似乎遇到 sched_scheduler() 进程挂起。包括下面的代码...replay1 和 replay2 是两个程序,分别简单地打印“Replay1”和“Replay2”。

# include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sched.h>


void main()
{
 int i,pid[5],pidparent,new=0;
 char *newargv1[] = {"./replay1",NULL};
 char *newargv2[] = {"./replay2",NULL};
 char *newenviron[] = {NULL};
 struct sched_param mysched;
 mysched.sched_priority = 1;
 sched_setscheduler(0,SCHED_FIFO, &mysched);  
 pidparent =getpid();

 for(i=0;i<2;i++)
 {
   if(getpid()==pidparent)
   {
    pid[i] = fork();
    if(pid[i] != 0)
    kill(pid[i],SIGSTOP);
    if(i==0 && pid[i]==0)
     execve(newargv1[0], newargv1, newenviron);
    if (i==1 && pid[i]==0)
     execve(newargv2[0], newargv2, newenviron);       
   }
 }
for(i=0;i<10;i++)
 {
   if(new==0)
    new=1;
   else
    new=0;
   kill(pid[new],SIGCONT);
   sleep(100);
   kill(pid[new], SIGSTOP);
 }


}

In a C program on Linux, I fork() followed by execve() twice to create two processes running two seperate programs. How do I make sure that the execution of the two child processes interleave?
Thanks
Tried to do the above task as an answer given below had suggested but seems on encountering sched_scheduler() process hangs. Including code below...replay1 and replay2 are two prograns which simply prints "Replay1" and "Replay2" respectively.

# include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sched.h>


void main()
{
 int i,pid[5],pidparent,new=0;
 char *newargv1[] = {"./replay1",NULL};
 char *newargv2[] = {"./replay2",NULL};
 char *newenviron[] = {NULL};
 struct sched_param mysched;
 mysched.sched_priority = 1;
 sched_setscheduler(0,SCHED_FIFO, &mysched);  
 pidparent =getpid();

 for(i=0;i<2;i++)
 {
   if(getpid()==pidparent)
   {
    pid[i] = fork();
    if(pid[i] != 0)
    kill(pid[i],SIGSTOP);
    if(i==0 && pid[i]==0)
     execve(newargv1[0], newargv1, newenviron);
    if (i==1 && pid[i]==0)
     execve(newargv2[0], newargv2, newenviron);       
   }
 }
for(i=0;i<10;i++)
 {
   if(new==0)
    new=1;
   else
    new=0;
   kill(pid[new],SIGCONT);
   sleep(100);
   kill(pid[new], SIGSTOP);
 }


}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

北座城市 2024-11-12 13:25:27

由于您需要随机交错,因此有一个可怕的技巧来做到这一点:

  • 分叉后立即向每个应用程序发送一个 SIGSTOP
  • 使用 sched_setscheduler 将您的父应用程序设置为具有实时优先级。这将使您拥有更细粒度的计时器。
  • 向子进程之一发送 SIGCONT。
  • 循环:等待一段随机的、短的时间。向当前运行的应用程序发送 SIGSTOP,向另一个应用程序发送 SIGCONT。重复。

这将有助于强制执行交错。这也会使事情变得相当缓慢。您可能还想尝试使用 sched_setaffinity 将每个进程分配给不同的 CPU(如果您有双核或超线程 CPU) - 这将导致它们有效地同时运行,模等待时间为 I /O。通过确保它们正在操作的任何数据都位于 ramdisk 上,可以避免 I/O 等待时间(这可能导致它们等待硬盘,此时它们可能会按顺序唤醒,因此不会交错)在 Linux 上,使用 tmpfs)。

如果这对您来说太粗粒度,您可以使用 ptrace 的 PTRACE_SINGLESTEP 操作一次执行一个 CPU 操作,按照您认为合适的方式进行交错。

Since you need random interleaving, here's a horrible hack to do it:

  • Immediately after forking, send a SIGSTOP to each application.
  • Set your parent application to have real-time priority with sched_setscheduler. This will allow you to have more fine-grained timers.
  • Send a SIGCONT to one of the child processes.
  • Loop: Wait a random, short time. Send a SIGSTOP to the currently-running application, and a SIGCONT to the other. Repeat.

This will help force execution to interleave. It will also make things quite slow. You may also want to try using sched_setaffinity to assign each process to a different CPU (if you have a dual-core or hyperthreaded CPU) - this will cause them to effectively run simultaneously, modulo wait times for I/O. I/O wait times (which could cause them to wait for the hard disk, at which point they're likely to wake up sequentially and thus not interleave) can be avoided by making sure whatever data they're manipulating is on a ramdisk (on linux, use tmpfs).

If this is too coarse-grained for you, you can use ptrace's PTRACE_SINGLESTEP operation to step one CPU operation at a time, interleaving as you see fit.

回眸一笑 2024-11-12 13:25:27

由于这是出于测试目的,您可以在子进程中的每行代码之后放置 sched_yield(); 调用。


另一个潜在的想法是让父进程 ptrace() 包含子进程,并使用 PTRACE_SINGLESTEP 在逐条指令的基础上交错两个进程的执行。

As this is for testing purposes, you could place sched_yield(); calls after every line of code in the child processes.


Another potential idea is to have a parent process ptrace() the child processes, and use PTRACE_SINGLESTEP to interleave the two process's execution on an instruction-by-instruction basis.

好倦 2024-11-12 13:25:27

如果您需要同步它们并且它们是您自己的进程,请使用信号量。如果您无权访问源,则无法同步它们。

if you need to synchronize them and they are your own processes, use semaphores. If you do not have access to the source, then there is no way to synchronize them.

诠释孤独 2024-11-12 13:25:27

如果您的目标是进行并发测试,我只知道两种技术:

  • 使用同步测试确切的场景。例如,进程 1 打开连接并执行查询,然后进程 2 进入并执行查询,然后进程 1 再次激活并获取结果,等等。您可以使用其他人提到的同步技术来完成此操作。然而,获得良好的测试场景非常困难。我过去很少使用这种方法。

  • 您信任的随机:启动大量测试进程来执行长时间运行的测试套件。我使用这种方法进行多线程和多进程测试(我的案例是测试来自多个进程的设备驱动程序访问而没有蓝屏)。通常,您希望使每个进程的测试套件的进程数和迭代次数可配置,以便您可以在发布之前进行快速通过或进行较长的测试(使用 10 个进程运行此类测试 10-12小时对我们来说并不罕见)。此类测试的通常运行以小时为单位。您只需启动进程,让它们运行几个小时,并希望它们能够捕获所有计时窗口。交错通常由操作系统处理,因此您实际上不需要在测试过程中担心它。

If your aim is to do concurrency testing, I know of only two techniques:

  • Test exact scenarios using synchronization. For example, process 1 opens a connection and executes a query, then process 2 comes in and executes a query, then process1 gets active again and gets the results, etc. You do this with synchronization techniques mentioned by others. However, getting good test scenarios is very difficult. I have rarely used this method in the past.

  • In random you trust: fire up a high number of test processes that execute a long running test suite. I used this method for both multithreading and multiprocess testing (my case was testing device driver access from multiple processes without blue screening out). Usually you want to make the number of processes and number of iterations of the test suite per process configurable so that you can either do a quick pass or do a longer test before a release (running this kind of test with 10 processes for 10-12 hours was not uncommon for us). A usual run for this sort of testing is measured in hours. You just fire up the processes, let them run for a few hours, and hope that they will catch all the timing windows. The interleaving is usually handled by the OS, so you don't really need to worry about it in the test processes.

柳若烟 2024-11-12 13:25:27

使用 Bash 而不是 C 来控制作业要简单得多。试试这个:

#! /bin/bash

stop ()
{
    echo "$1 stopping"
    kill -SIGSTOP $2
}

cont ()
{
    echo "$1 continuing"
    kill -SIGCONT $2
}

replay1 ()
{
    while sleep 1 ; do echo "replay 1  running" ; done
}

replay2 ()
{
    while sleep 1 ; do echo "replay  2 running" ; done
}

replay1 &
P1=$!
stop "replay 1" $P1

replay2 &
P2=$!
stop "replay  2" $P2

trap "kill $P1;kill $P2" EXIT

while sleep 1 ; do 
    cont "replay 1 " $P1
    cont "replay  2" $P2
    sleep 3
    stop "replay 1 " $P1
    stop "replay  2" $P2
done

两个进程并行运行:

$ ./interleave.sh
replay 1 stopping
replay  2 stopping
replay 1  continuing
replay  2 continuing
replay  2 running
replay 1  running
replay 1  running
replay  2 running
replay 1  stopping
replay  2 stopping
replay 1  continuing
replay  2 continuing
replay 1  running
replay  2 running
replay  2 running
replay 1  running
replay  2 running
replay 1  running
replay 1  stopping
replay  2 stopping
replay 1  continuing
replay  2 continuing
replay 1  running
replay  2 running
replay 1  running
replay  2 running
replay 1  running
replay  2 running
replay 1  stopping
replay  2 stopping
^C

Job control is much simpler with the Bash instead of C. Try this:

#! /bin/bash

stop ()
{
    echo "$1 stopping"
    kill -SIGSTOP $2
}

cont ()
{
    echo "$1 continuing"
    kill -SIGCONT $2
}

replay1 ()
{
    while sleep 1 ; do echo "replay 1  running" ; done
}

replay2 ()
{
    while sleep 1 ; do echo "replay  2 running" ; done
}

replay1 &
P1=$!
stop "replay 1" $P1

replay2 &
P2=$!
stop "replay  2" $P2

trap "kill $P1;kill $P2" EXIT

while sleep 1 ; do 
    cont "replay 1 " $P1
    cont "replay  2" $P2
    sleep 3
    stop "replay 1 " $P1
    stop "replay  2" $P2
done

The two processes are running in parallel:

$ ./interleave.sh
replay 1 stopping
replay  2 stopping
replay 1  continuing
replay  2 continuing
replay  2 running
replay 1  running
replay 1  running
replay  2 running
replay 1  stopping
replay  2 stopping
replay 1  continuing
replay  2 continuing
replay 1  running
replay  2 running
replay  2 running
replay 1  running
replay  2 running
replay 1  running
replay 1  stopping
replay  2 stopping
replay 1  continuing
replay  2 continuing
replay 1  running
replay  2 running
replay 1  running
replay  2 running
replay 1  running
replay  2 running
replay 1  stopping
replay  2 stopping
^C
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文