FIFO (segmentation fault)

Модератор: Модераторы разделов

Аватара пользователя
fatboy
Сообщения: 156
ОС: Zenwalk Linux, Windows XP

FIFO

Сообщение fatboy »

Помогите пожалуйста разобраться с FIFO и иже с ним.
Проблема в том что написав, скомпилив и запустив такую вещь:

Код: Выделить всё

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/stat.h>

#define FIFO_FILE "MYFIFO"

int main(void){
    FILE *fp_c=0, *fp_s=0;
    char readbuf[80];
    pid_t pid;
    
    umask(0);
    mknod(FIFO_FILE, S_IFIFO-0666, 0);
    pid=fork();
    printf("Pid: %d\n", pid);
    if(pid==-1){
    perror("fork");
    }
    else{
    if(pid==0){
     printf("%d", pid);
     fp_c=fopen(FIFO_FILE, "w");
     printf("%d", fp_c);
     fputs("Hello, Parent!", fp_c);
     fclose(fp_c);
     exit(0);
    }
    else{
     fp_s=fopen(FIFO_FILE, "r");
     fgets(readbuf, 80, fp_s);
     printf("Recieved string: %s\n", readbuf);
     fclose(fp_s);
    }
    }
    unlink(FIFO_FILE);
    return 0;
}


Получаю

Код: Выделить всё

 Segmentation fault


Немного исследовав этот ОГРОМНЫЙ проект :D , обнаружил, что ошибку вызывают:

Код: Выделить всё

fputs("Hello, Parent!", fp_c);
fgets(readbuf, 80, fp_s);
fclose();


Последняя же вызывает подобную ошибку в любой проге даже не связанной с FIFO.

Компилил:

Код: Выделить всё

gcc -o mfifo mfifo.c
Ниединого предупреждения.

И еще: как может fork() возвращать при успешном выполнении 0 и PID нового процесса?
Zenwalk 4.0
TOSHIBA Satellite A100
Спасибо сказали:
Аватара пользователя
FreeNUX
Сообщения: 185
Статус: с сириуса
ОС: FreeBSD 6.2

Re: FIFO

Сообщение FreeNUX »

И еще: как может fork() возвращать при успешном выполнении 0 и PID нового процесса?

К примеру так

Код: Выделить всё

main()
{
    pid_t pid;

    switch(pid = fork())
    {
    case -1:
  printf("Ошибка вызова fork()\n");
  break;
    case 0: /*потомок*/
  printf("Потомок %d\n", getpid() ); /*получаем pid потомка*/

    default: /*родитель*/

    }
  return 0;
}

Для получения PID родительского процесса используй getppid(); .
Аркона – лишь тихие воды,
Кровью варяжской янтарь в них застыл.
Аркона – там ветер со взморья
В трещинах скал своё сердце забыл.
Темнозорь - Аркона (Вольницей В Просинь Ночей - 2005)
Спасибо сказали:
Аватара пользователя
Alagert
Сообщения: 167

Re: FIFO

Сообщение Alagert »

В случаи успешного выполнения fork() и так возвращает PID сына. Если что то случилось не так, то вернет -1. Если из сына нужно получить PID родителя, то getppid();

Немного исследовав этот ОГРОМНЫЙ проект biggrin.gif , обнаружил, что ошибку вызывают:

Код: Выделить всё

fputs("Hello, Parent!", fp_c);
fgets(readbuf, 80, fp_s);
fclose();


Так а ты уверен, что у тебя ФИФО норм создается. Проверь что возвращает fopen для fp_s, fp_c.

PS а ты не в Питерском политехе учишься на ФТК?

Alagert добавил в 05.06.2005 20:13

Я не уверен, что именно в этом дело, но:
1)Открывать ФИФО фроде нужно так:

Код: Выделить всё

mknod(FIFO_FILE, S_IFIFO | 0666, 0);

2) открывать на запись:

Код: Выделить всё

int writefd;
if((writefd = open(FIFO, O_WRONLY)) < 0){
printf(“Невозможно открыть FIFO\n”); exit(1); }

И Записывать так:

Код: Выделить всё

if(write(writefd, “Здравствуй, Мир!\n”, 18) != 18){
printf(“Ошибка записи\n”); exit(1); }

3) Открывать на чтение:

Код: Выделить всё

int readfd;
if((readfd = open(FIFO, O_RDONLY)) < 0){
printf(“Невозможно открыть FIFO\n”); exit(1);}

А читать так:

Код: Выделить всё

int n;
while((n = read(readfd, buff, MAXBUFF)) > 0)


Надеюсь поможет!
Born to be ROOT
Спасибо сказали:
Аватара пользователя
FreeNUX
Сообщения: 185
Статус: с сириуса
ОС: FreeBSD 6.2

Re: FIFO

Сообщение FreeNUX »

Для открытия fifo, также можно использовать функцию

Код: Выделить всё

int mkfifo(const char *pathname, mode_t mode);
Аркона – лишь тихие воды,
Кровью варяжской янтарь в них застыл.
Аркона – там ветер со взморья
В трещинах скал своё сердце забыл.
Темнозорь - Аркона (Вольницей В Просинь Ночей - 2005)
Спасибо сказали:
Аватара пользователя
Sparky
Сообщения: 604
Статус: core dumped
ОС: Plan 9

Re: FIFO

Сообщение Sparky »

(fatboy @ Воскресенье, 05 Июня 2005, 15:15) писал(а):И еще: как может fork() возвращать при успешном выполнении 0 и PID нового процесса?

man fork:

Код: Выделить всё

   При успешном завершении родителю возвращается PID дочернего процесса, а дочернему процессу возвращается 0.  При неудаче родительскомупроцессу возвращается -1, дочернего процесса не создается, а errno выставляется должным образом.
Блог
--------------------

GCS/M/MU/P/IT/E d- s: a- C++(+++) UBL++ P->-- L+++$ E- W+++$ N* o? K? w>--
O M-@ V- PS@ PE+ Y+ PGP+ t 5 X R* tv-->- b++ DI? D>+ G e+(++) h--- r+ y++
Спасибо сказали:
Аватара пользователя
fatboy
Сообщения: 156
ОС: Zenwalk Linux, Windows XP

Re: FIFO

Сообщение fatboy »

(Alagert @ Воскресенье, 05 Июня 2005, 19:13) писал(а):1)Открывать ФИФО фроде нужно так:

Код: Выделить всё

mknod(FIFO_FILE, S_IFIFO | 0666, 0);

Спасибо ОГРОМНОЕ ! Действительно не так открывал!

а ты не в Питерском политехе учишься на ФТК?

К огромному сожалению - Нет :(

fatboy добавил в 06.06.2005 01:32

(Sparky @ Воскресенье, 05 Июня 2005, 22:09) писал(а):
(fatboy @ Воскресенье, 05 Июня 2005, 15:15) писал(а):И еще: как может fork() возвращать при успешном выполнении 0 и PID нового процесса?

man fork:

Код: Выделить всё

   При успешном завершении родителю возвращается PID дочернего процесса, а дочернему процессу возвращается 0.  При неудаче родительскомупроцессу возвращается -1, дочернего процесса не создается, а errno выставляется должным образом.




Да читал я man, просто еще слабо доганяю: вот етот блок

Код: Выделить всё

switch(pid = fork())
 {
 case -1:
  printf("Ошибка вызова fork()\n");
  break;
 case 0: /*потомок*/
  printf("Потомок %d\n", getpid() ); /*получаем pid потомка*/

 default: /*родитель*/

 }

анализирует ведь pid(переменную) а в pid fork() возвращает одно значение?.. и анализирует pid родитель или уже потомок? И как мы попадаем внутрь

Код: Выделить всё

case 0:
...
break;

если родитель получил какой-то pid, отличный от 0? Должны же попасть в

Код: Выделить всё

default:
...
break;

или как? :wacko:
Zenwalk 4.0
TOSHIBA Satellite A100
Спасибо сказали:
Аватара пользователя
Alagert
Сообщения: 167

Re: FIFO

Сообщение Alagert »

Если грубо, то можно сказать так: если PID=0 то работает потомок. Так и получается, что в

Код: Выделить всё

case 0:
...
break;

Будет работать потомок!
Born to be ROOT
Спасибо сказали:
Аватара пользователя
d_Sun
Сообщения: 291

Re: FIFO

Сообщение d_Sun »

В общем случае системный вызов fork() работает так:
- родитель вызывает fork()
- fork() создает новый ( дочерний ) процесс - который является копией родителя
- управление возвращается в оба процесса ( с pid=0 дочернему )
- после этого процессы находятся в одной и той-же точке программы
- ну а ветвление происходит по значению pid.
Моя подпись сильно длинная :)
Спасибо сказали:
Аватара пользователя
fatboy
Сообщения: 156
ОС: Zenwalk Linux, Windows XP

Re: FIFO

Сообщение fatboy »

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

Код: Выделить всё

case 0:
...
break;

? Так? А весь код родителя - в

Код: Выделить всё

default:
...
break;

?
Zenwalk 4.0
TOSHIBA Satellite A100
Спасибо сказали:
Аватара пользователя
d_Sun
Сообщения: 291

Re: FIFO

Сообщение d_Sun »

(fatboy @ Понедельник, 06 Июня 2005, 11:30) писал(а):Т.е. получается, что пока не вызван exec() выполняются два абсолютно одинковых процесса? Т.е. весь код нового процесса должен быть помещен в

Код: Выделить всё

case 0:
...
break;

? Так? А весь код родителя - в

Код: Выделить всё

default:
...
break;

?


Ну в общем да :) Советую прочитать, что собственно делают системные вызовы fork() и exec() - вопросов станет меньше! Просто FIFO - это уже средство IPC, а вы, судя по всему, еще с процессами не разобрались!
Моя подпись сильно длинная :)
Спасибо сказали: