fprintf печатает данные в неправильном порядке - PullRequest
0 голосов
/ 28 апреля 2011

У меня есть программа на языке Си, которая выводит некоторые данные на стандартный вывод.Я использовал printf для этого, но мне нужно также сохранить данные в файл, поэтому я изменил его на fprintf.Проблема в том, что при использовании fprintf данные располагаются в неправильном порядке, не имеет значения, если вывод является stdout или файлом.

  if(...) {
    out = fopen(param.F, "w");
  } else {
    out = stdout;
  }

  // some code here
  fprintf(out, "a");
  // more code
  fprintf(out, "b");
  ....

В этом случае вывод всегда отличается.Иногда это

acb

Иногда это

cab

и т.д. ... Я пробовал различные комбинациииз setbuf и fflush, но ни один из них не помог.

РЕДАКТИРОВАТЬ: Может быть важно знать, что я использую некоторые fork() в моей программе, но, как я упоминал ранее, нет проблем при использовании printf.

Вот мой вывод:

1: парикмахер: чеки

2: клиент 1: создан

3: клиент 1: входит

5: парикмахер: готов

6: клиент 1: готов

4: клиент 2: создан

7: парикмахер: закончен

8: парикмахер: чеки

9: клиент 2: входит

10: клиент 1: обслуживается

11: парикмахер: готов

12: клиент 2: готов

13: цирюльник: готово

14: цирюльник: чеки

15: покупатель 2: обслуживается

Заказывается по номерам.Программа имеет такую ​​структуру:

int main() {
  pid = fork();
  if(pid == 0) {
    // barber printfs
  } else if (pid > 0) {
    // customer printfs
  } 
}

Ответы [ 2 ]

2 голосов
/ 18 января 2013

(не могу комментировать, должен ответить ...)

Нет, дело не в том, что printf / fprintf буферизует иначе, объект FILE * одинаков, если вы выполняете fprintf (stdout, ...) или printf (....).

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

1 голос
/ 28 апреля 2011

printf и fprintf будут иметь различную буферизацию драйвера устройства.

Поскольку вы говорите, что используете fork, и, основываясь на выводе, я предполагаю, что код похож на

  1. Открыть файл
  2. Вилка
  3. Записать данные

В этом случае возникает другой порядок, потому что запись происходит в случайном порядке, в зависимости от того, когдакаждый дочерний процесс назначается по расписанию.

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

Если вам нужно более сложное решение, вам нужно настроить механизм IPC между процессами и выполнить все записи в родительском объекте.

Один из подходов - установить для stdout значениеканал (от socketpair ) до разветвления и чтения из канала в родительском процессе (используя select (), чтобы избежать блокировки), затем войдите в экран / файл.Вам нужно будет использовать dup () stdout перед использованием freopen, чтобы не потерять его.Вероятно, я пропустил несколько вещей, так как некоторое время не делал этого.

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