LINUX.ORG.RU

Критическая секция


0

0

Программа создает процессы с помощью fork , которые получают доступ к стандартному выводу ошибок . Порядок вывода произвольный .
Можно ли его упорядочить по возрастанию , не используя блокировку ?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

#define BUFSIZE 1024

int main(int argc, char *argv[]) {
    char buffer[BUFSIZE];
    char *c;
    pid_t childpid = 0;
    int delay;
    volatile int dummy = 0;
    int i, n;

    if (argc != 3){   /* check for valid number of command-line arguments */
        fprintf (stderr, "Usage: %s processes delay\n", argv[0]);
        return 1;
    }
    n = atoi(argv[1]);
    delay = atoi(argv[2]);
    for (i = 1; i < n; i++)
        if (childpid = fork())
            break;
    snprintf(buffer, BUFSIZE,
             "i:%d  process ID:%ld  parent ID:%ld  child ID:%ld\n",
             i, (long)getpid(), (long)getppid(), (long)childpid);

    c = buffer;
   /********************** start of critical section **********************/
    while (*c != '\0') {
        fputc(*c, stderr);
        c++;
        for (i = 0; i < delay; i++)
            dummy++;
    }
   /********************** end of critical section ************************/
    if (wait(NULL) == -1)
        return 1;
    return 0;
}

★★★★★

> Программа создает процессы с помощью fork , которые получают доступ к стандартному выводу ошибок . Порядок вывода произвольный .

> Можно ли его упорядочить по возрастанию , не используя блокировку ?

По возрастанию чего? Если ты хочешь выводить сообщения по возрастанию какого-то произвольного критерия, получается что перед тем как вывести некое сообщение MSG1, тебе нужно дождаться окончания всех форков (а вдруг какой-нибудь из них напечатает сообщение MSG2 < MSG1). Тут блокировки не нужны - пусть каждый валит в свой буфер, а печатающий тред в конце сортирует и печатает :-))

Или у тебя есть как минимум ограничение что каждый процесс плюется упорядоченным набором сообщений?

gods-little-toy ★★★
()
Ответ на: комментарий от kto_tama

> имеется расшаренный ресурс - stderr

То есть надо сделать чтобы записанное в stderr не перемешивалось? Тогда - либо мутексы (те блокировки), либо какие-нибудь игры с включением/выключением буферизации и надеждой на то что то, если ты пишешь одним вызовом записи, то другие не смогут вклиниться.

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

Если пишутся огромные объемы и машина существенно многоядерная, может поможет создание каждому форку своего stderr, указывающего на пайп, с другой стороны которого сидит сливающий все эти упорядоченные потоки вместе. Но это уже для экзотических случаев.

gods-little-toy ★★★
()

Если печатать нехитрый вывод, то можно переопределить printf через define секцией, которая сначала печатает что-то вроде MSG From x pid. А затем отрабатывает обычный printf.

help_us
()

Ваш код:

while (*c != '\0') {
fputc(*c, stderr);
c++;
for (i = 0; i < delay; i++)
dummy++;
}

непонятен, так как вы пишете в поток stderr, там своя буферезация. В линуксе write() атомарен (во всяком случае при выводе в файл на НЖМД), поэтому, если у вас будет write(2, buffer, strlen(buffer)), то сообщение от каждого потомка будет идти отдельной строкой, тогда можно и sort на вывод делать.

mky ★★★★★
()

Без семафоров никак. Либо, если хочется делать извращения с delay:

    while (*c != '\0') {
        c++;
        for (i = 0; i < delay; i++)
            dummy++;
    }
    fprintf(stderr, buffer)

Reset ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.