Убедиться, что два процесса чередуются - PullRequest
2 голосов
/ 06 мая 2011

В программе на C на Linux я выполняю 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);
 }


}

Ответы [ 5 ]

3 голосов
/ 06 мая 2011

Так как вам нужно случайное чередование, вот ужасный хак, чтобы сделать это:

  • Сразу после разветвления отправьте SIGSTOP каждому приложению.
  • Установите для родительского приложения приоритет в реальном времени с помощью sched_setscheduler. Это позволит вам иметь более мелкозернистые таймеры.
  • Отправка SIGCONT одному из дочерних процессов.
  • Цикл: подождите случайное, короткое время. Отправьте SIGSTOP в текущее приложение, а SIGCONT - в другое. Повторите.

Это поможет принудительно чередовать выполнение. Это также сделает вещи довольно медленными. Вы также можете попытаться использовать sched_setaffinity, чтобы назначить каждому процессу отдельный ЦП (если у вас двухъядерный или многопоточный ЦП) - это заставит их эффективно работать одновременно, по модулю времени ожидания ввода-вывода. Время ожидания ввода / вывода (которое может привести к тому, что они будут ждать жесткого диска, и в этот момент они могут проснуться последовательно и, следовательно, не будут чередоваться), можно избежать, если убедиться, что все данные, которыми они манипулируют, находятся на виртуальном диске в Linux используйте tmpfs).

Если это слишком грубо для вас, вы можете использовать операцию ptrace PTRACE_SINGLESTEP, чтобы выполнять по одной операции ЦП за раз, чередуя по своему усмотрению.

2 голосов
/ 06 мая 2011

Поскольку это делается для целей тестирования, вы можете делать sched_yield(); вызовы после каждой строки кода в дочерних процессах.


Другая потенциальная идея состоит в том, чтобы иметь родительский процесс ptrace() дочерний процесс и использовать PTRACE_SINGLESTEP для чередования выполнения двух процессов на основе инструкции за инструкцией.

1 голос
/ 06 мая 2011

если вам нужно синхронизировать их, и они являются вашими собственными процессами, используйте семафоры. Если у вас нет доступа к источнику, то нет возможности их синхронизировать.

0 голосов
/ 08 мая 2011

Управление заданиями намного проще с 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
0 голосов
/ 06 мая 2011

Если ваша цель - провести параллельное тестирование, я знаю только два метода:

  • Тестирование точных сценариев с использованием синхронизации.Например, процесс 1 открывает соединение и выполняет запрос, затем входит процесс 2 и выполняет запрос, затем процесс 1 снова активируется и получает результаты и т. Д. Это делается с помощью методов синхронизации, упомянутых другими.Однако получить хорошие тестовые сценарии очень сложно.В прошлом я редко использовал этот метод.

  • В случайном порядке вы доверяете: запустите большое количество тестовых процессов, которые выполняют длительный набор тестов.Я использовал этот метод как для многопоточности, так и для многопроцессорного тестирования (в моем случае это тестирование доступа к драйверу устройства из нескольких процессов без «синего экрана»).Обычно вы хотите настроить количество процессов и количество итераций набора тестов для каждого процесса, чтобы можно было либо выполнить быстрый проход, либо выполнить более длинный тест перед выпуском (запуск такого теста с 10 процессами в течение 10-12часы не были редкостью для нас).Обычный пробег для такого рода испытаний измеряется в часах.Вы просто запускаете процессы, позволяете им работать в течение нескольких часов и надеетесь, что они поймают все окна синхронизации.Чередование обычно выполняется ОС, поэтому вам не нужно беспокоиться об этом в процессе тестирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...