C++ в Linux: пайпы
Модератор: Модераторы разделов
-
Xaktyc
- Сообщения: 604
- ОС: Gentoo 2008.0, WinXP
C++ в Linux: пайпы
Имеется задание сделать вычисление формулы по частям - в трех форках.
Первая часть задания - сделать связь через файлы и переменные выполнить.
Затруднения с третьей задачей - связь через пайпы.
Где можно почитать что-нибудь понятное для новичка в C про пайпы?
Ну или буду очень благодарен за небольшой пример как можно из дочернего в главный процесс через пайп передать значение переменной.
Первая часть задания - сделать связь через файлы и переменные выполнить.
Затруднения с третьей задачей - связь через пайпы.
Где можно почитать что-нибудь понятное для новичка в C про пайпы?
Ну или буду очень благодарен за небольшой пример как можно из дочернего в главный процесс через пайп передать значение переменной.
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: C++ в Linux: пайпы
У меня на столе лежит хорошая книжка: Уильям Стивенс "UNIX. Взаимодействие процессов" 
Там и про shm, и про потоки/нити FIFO/LIFO и пр. Т.к. вам нужно ожидать завершения выполнения дочерних процессов (или нитей), то придется использовать, например, семафоры, либо запускать дочерний поток и ждать его завершения. А значение переменной не обязательно передавать через каналы - можно и разделяемую память использовать.
Там и про shm, и про потоки/нити FIFO/LIFO и пр. Т.к. вам нужно ожидать завершения выполнения дочерних процессов (или нитей), то придется использовать, например, семафоры, либо запускать дочерний поток и ждать его завершения. А значение переменной не обязательно передавать через каналы - можно и разделяемую память использовать.
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
begin2009
- Сообщения: 349
- Статус: Ламер со стажем
- ОС: без глюков
Re: C++ в Linux: пайпы
Посмотрите сюды
Все подробно, с кучей примеров.
Все подробно, с кучей примеров.
Пессимист видит темный туннель, оптимист видит свет в конце туннеля, реалист видит свет, туннель и поезд.
И только машинист видит этих трех идиотов, сидящих на рельсах.
И только машинист видит этих трех идиотов, сидящих на рельсах.
-
Xaktyc
- Сообщения: 604
- ОС: Gentoo 2008.0, WinXP
Re: C++ в Linux: пайпы
Там ожидается завершения. Все что надо уже сделано. Надо то же самое тока под пайпы переделать...
Спасибо. Завтра попытаюсь осилить.
-
NickLion
- Сообщения: 3408
- Статус: аватар-невидимка
- ОС: openSUSE Tumbleweed x86_64
Re: C++ в Linux: пайпы
Ой, раз задали вопрос про пайпы... Давно висит задачка, всё никак не вернусь к ней. В общем суть такая: имеется N процессов, каждый из них связан через пайпы с нулевым
. В определенный момент времени двум процессам надо организовать общение, но не через 0-й (чтобы не нагружать). Можно ли обойтись безымянными пайпами? Или придется всё же делать FIFO (aka именованные пайпы)?
-
Slimy
- Сообщения: 1689
- ОС: openSuSE 11.2 GM (GеMор едишн)
Re: C++ в Linux: пайпы
А что есть pid=0? просто там в примерах на основании этого направление передачи через пайп выбирается.
Если уже ничего не помогает - прочти инструкцию.
sysinstall - гадость :)
ASUS A6q00Vm Pentium-M 1.7 GHz, 2Gb RAM, 160Gb HDD,
GeForce Go 7300 64Mb video
sysinstall - гадость :)
ASUS A6q00Vm Pentium-M 1.7 GHz, 2Gb RAM, 160Gb HDD,
GeForce Go 7300 64Mb video
-
begin2009
- Сообщения: 349
- Статус: Ламер со стажем
- ОС: без глюков
Re: C++ в Linux: пайпы
PID - положительное целое число, однозначно идентифицирующее процесс в течение времени его жизни. Процессов с PID==0 не будет в принципе. Для текущего контроля состояния процессов в системе используется команда ps. Заданная без параметров, она выводит список PID процессов данного пользователя, с опцией -A - список всех процессов в системе. Запустите в терминале. Все PID - многозначные числа. В программе PID можно получить функцией getpid() с прототипом:
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
(Тип данных pid_t является синонимом для одного из целочисленных типов языка C).
В примерах если PID нулевой, то это признак что такого процесса нет.
Пессимист видит темный туннель, оптимист видит свет в конце туннеля, реалист видит свет, туннель и поезд.
И только машинист видит этих трех идиотов, сидящих на рельсах.
И только машинист видит этих трех идиотов, сидящих на рельсах.
-
Slimy
- Сообщения: 1689
- ОС: openSuSE 11.2 GM (GеMор едишн)
Re: C++ в Linux: пайпы
begin2009 писал(а): ↑04.12.2009 18:35
PID - положительное целое число, однозначно идентифицирующее процесс в течение времени его жизни. Процессов с PID==0 не будет в принципе. Для текущего контроля состояния процессов в системе используется команда ps. Заданная без параметров, она выводит список PID процессов данного пользователя, с опцией -A - список всех процессов в системе. Запустите в терминале. Все PID - многозначные числа. В программе PID можно получить функцией getpid() с прототипом:
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
(Тип данных pid_t является синонимом для одного из целочисленных типов языка C).
В примерах если PID нулевой, то это признак что такого процесса нет.
спасибо за подробности про pid я в курсе был просто предполагал что 0 какой то особый смысл имеет просто в примере
Код: Выделить всё
if((childpid = fork()) == -1)
{
perror("fork");
exit(1);
}
if(childpid == 0)
{
/* Потомок закрывает вход */
close(fd[0]);
}
else
{
/* Родитель закрывает выход */
close(fd[1]);
}Если уже ничего не помогает - прочти инструкцию.
sysinstall - гадость :)
ASUS A6q00Vm Pentium-M 1.7 GHz, 2Gb RAM, 160Gb HDD,
GeForce Go 7300 64Mb video
sysinstall - гадость :)
ASUS A6q00Vm Pentium-M 1.7 GHz, 2Gb RAM, 160Gb HDD,
GeForce Go 7300 64Mb video
-
pcodr
- Сообщения: 283
- ОС: Debian
Re: C++ в Linux: пайпы
В потомке fork возвращает 0, в родителе pid потомка, при неудаче -1 в родителе.
man fork
man fork
remote system type is unix
-
Xaktyc
- Сообщения: 604
- ОС: Gentoo 2008.0, WinXP
Re: C++ в Linux: пайпы
Насколько я помню, если ты делаешь что-то типа
int pid=fork();
тогда pid=номеру форка. Если правильно составить условие - тогда если 0 - выполнение ведется в родителе, если нет - в форке.
int pid=fork();
тогда pid=номеру форка. Если правильно составить условие - тогда если 0 - выполнение ведется в родителе, если нет - в форке.
-
begin2009
- Сообщения: 349
- Статус: Ламер со стажем
- ОС: без глюков
Re: C++ в Linux: пайпы
Подправлюсь, действительно у работающего процесса из консоли pid равный нулю мы не найдем. А вот если форком запустим другой процесс, то да. У порожденного процесса по сравнению с процессом-предком изменяются значения следующих параметров: идентификатор процесса - PID; идентификатор родительского процесса - PPID.
Для иллюстрации сказанного рассмотрим программу:
Системный вызов fork() возвращает в процессы предок и потомок различные значения. При успешном создании нового процесса в процесс-предок возвращается
положительное значение, равное идентификатору процесса-потомка. В процесс-потомок же возвращается значение 0. Если по какой-либо причине создать новый
процесс не удалось, то системный вызов вернет в инициировавший его процесс значение -1.
PS Скопировал из лекций по операционным системам у сына. Копирайт на текст у его препода.
Для иллюстрации сказанного рассмотрим программу:
Код: Выделить всё
/* Программа fork.с - пример создания нового процесса
с одинаковой работой процессов предка и потомка */
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t pid, ppid;
int a = 0;
fork();
/* При успешном создании нового процесса
с этого места псевдопараллельно
начинают работать два процесса: старый
и новый */
/* Перед выполнением следующего выражения
значение переменной a в обоих процессах
равно 0 */
++a;
/* Узнаем идентификаторы текущего и роди-
тельского процесса (в каждом из процессов !!!) */
pid = getpid();
ppid = getppid();
/* Печатаем значения PID, PPID и вычислен-
ное значение переменной a (в каждом из процессов !!!) */
printf("My pid = %d, my ppid = %d, result = %d\n",
(int)pid, (int)ppid, a);
getchar();
return 0;
}Системный вызов fork() возвращает в процессы предок и потомок различные значения. При успешном создании нового процесса в процесс-предок возвращается
положительное значение, равное идентификатору процесса-потомка. В процесс-потомок же возвращается значение 0. Если по какой-либо причине создать новый
процесс не удалось, то системный вызов вернет в инициировавший его процесс значение -1.
PS Скопировал из лекций по операционным системам у сына. Копирайт на текст у его препода.
Пессимист видит темный туннель, оптимист видит свет в конце туннеля, реалист видит свет, туннель и поезд.
И только машинист видит этих трех идиотов, сидящих на рельсах.
И только машинист видит этих трех идиотов, сидящих на рельсах.
-
Slimy
- Сообщения: 1689
- ОС: openSuSE 11.2 GM (GеMор едишн)
Re: C++ в Linux: пайпы
begin2009 писал(а): ↑05.12.2009 12:43Подправлюсь, действительно у работающего процесса из консоли pid равный нулю мы не найдем. А вот если форком запустим другой процесс, то да. У порожденного процесса по сравнению с процессом-предком изменяются значения следующих параметров: идентификатор процесса - PID; идентификатор родительского процесса - PPID.
Для иллюстрации сказанного рассмотрим программу:
Код: Выделить всё
/* Программа fork.с - пример создания нового процесса с одинаковой работой процессов предка и потомка */ #include <sys/types.h> #include <unistd.h> #include <stdio.h> int main() { pid_t pid, ppid; int a = 0; fork(); /* При успешном создании нового процесса с этого места псевдопараллельно начинают работать два процесса: старый и новый */ /* Перед выполнением следующего выражения значение переменной a в обоих процессах равно 0 */ ++a; /* Узнаем идентификаторы текущего и роди- тельского процесса (в каждом из процессов !!!) */ pid = getpid(); ppid = getppid(); /* Печатаем значения PID, PPID и вычислен- ное значение переменной a (в каждом из процессов !!!) */ printf("My pid = %d, my ppid = %d, result = %d\n", (int)pid, (int)ppid, a); getchar(); return 0; }
Системный вызов fork() возвращает в процессы предок и потомок различные значения. При успешном создании нового процесса в процесс-предок возвращается
положительное значение, равное идентификатору процесса-потомка. В процесс-потомок же возвращается значение 0. Если по какой-либо причине создать новый
процесс не удалось, то системный вызов вернет в инициировавший его процесс значение -1.
PS Скопировал из лекций по операционным системам у сына. Копирайт на текст у его препода.
Да спс теперь все понятно. ppid () это parent pid? Причем вроде как припоминаю в универе тоже подобный код видел. А вот в примерах двльше увидел.
char *strings[MAXSTRS] = {"echo", "bravo", "alpha", "charlie", "delta"};
к теме не относится но стало интересно как это в массив типа char стринги влезают?
Если уже ничего не помогает - прочти инструкцию.
sysinstall - гадость :)
ASUS A6q00Vm Pentium-M 1.7 GHz, 2Gb RAM, 160Gb HDD,
GeForce Go 7300 64Mb video
sysinstall - гадость :)
ASUS A6q00Vm Pentium-M 1.7 GHz, 2Gb RAM, 160Gb HDD,
GeForce Go 7300 64Mb video
-
Xaktyc
- Сообщения: 604
- ОС: Gentoo 2008.0, WinXP
Re: C++ в Linux: пайпы
Да.
Ну тут же вроде указатель на область. Если я не ошибаюсь, если писать в двойных кавычках - пишется некоторое количество символов. Если в одинарных - один символ.
ЗЫ. Вопрос: тут кто-нить код по топику привести может вообще?
-
pcodr
- Сообщения: 283
- ОС: Debian
Re: C++ в Linux: пайпы
Написал для пробы. Сам на си не пишу ибо сложный, так что за качество не ручаюсь.
Тут создаётся потомок, между родителем и потомком канал. Потомок вычисляет 10 больших простых чисел самым тормозным методом - методом перебора и по мере вычисления пишет их в канал, уведомляя об этом родителя с пмощью сигнала таймера. Родитель в свою очередь получив сигнал таймера читает из канала прешедшее число. Между тем родитель занят своими вычислениями, в данном случаи просто спит и печатает сообщения.
gcc -lm filename.c
Тут создаётся потомок, между родителем и потомком канал. Потомок вычисляет 10 больших простых чисел самым тормозным методом - методом перебора и по мере вычисления пишет их в канал, уведомляя об этом родителя с пмощью сигнала таймера. Родитель в свою очередь получив сигнал таймера читает из канала прешедшее число. Между тем родитель занят своими вычислениями, в данном случаи просто спит и печатает сообщения.
Код: Выделить всё
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<math.h>
int pipes[2];
void sig_chld(int sig)
{ // sigchld handler
int status;
// clean zombies
waitpid(-1, &status, WNOHANG);
puts("Child exit successfully");
}
void sig_alrm(int sig)
{ // sigalrm handler
int len;
char *buf;
buf = malloc(10);
len = read(pipes[0], buf, 9);
printf("received prime from child: %s\n", buf);
free(buf);
}
int rank_num(long long num)
{
int i = 1;
while(num % (long long)pow(10, i) != num)
{
i++;
}
return i;
}
int main()
{
pid_t child;
int i;
struct sigaction act;
// install sigchld handler
act.sa_handler = sig_chld;
if(sigaction(SIGCHLD, &act, NULL) == -1)
{
perror("sigaction failed");
return(1);
}
// install sigalrm handler
act.sa_handler = sig_alrm;
if(sigaction(SIGALRM, &act, NULL) == -1)
{
perror("sigaction failed");
return(1);
}
// create pipe
if(pipe(pipes) == -1)
{
perror("failed to create pipe");
return(1);
}
// fork
if((child = fork()) == -1)
{
perror("fork failed");
return(1);
}
if(!child)
{ // this is child
close(pipes[0]); // close unused pipe end: reader
// try to get next big prime (stupid way)
long long prime = 160481183;
int cnt, len;
char *buf = NULL;
pid_t parent;
// get parent pid
parent = getppid();
for(cnt=0; cnt<10;)
{ // try to find 10 primes
prime++;
for(i=2; i<prime; i++)
{
if(prime % i == 0)
{ // this is not prime
break;
}
}
if(i == prime)
{ // prime found, send it to parent
len = rank_num(prime);
buf = realloc(buf, len+1);
if(!buf)
{
perror("failed to realloc memory");
return(1);
}
sprintf(buf, "%d", prime);
write(pipes[1], buf, len);
// hay parent, there is a new data in the pipe
kill(parent, SIGALRM);
cnt++;
}
}
free(buf);
close(pipes[1]);
}
else
{ // this is parent
close(pipes[1]); // close unused pipe end: writer
for(i=0;;i++)
{ // parent do some job
printf("parent job: %d%\n", i);
sleep(3);
}
close(pipes[0]);
}
return 0;
}gcc -lm filename.c
remote system type is unix
-
RasenHerz
- Сообщения: 1341
- ОС: Arch Linux amd64
Re: C++ в Linux: пайпы
Почему бы не использовать вместо пайпов разделямую память? На мой взгляд, получится довольно аккуратно: создаете структуру со всеми необходимыми данными, заполняете ее, а потом копируете в разделяемую память ( c помощью того же memcpy ) - все.
-
Slimy
- Сообщения: 1689
- ОС: openSuSE 11.2 GM (GеMор едишн)
Re: C++ в Linux: пайпы
а может быть вы небольшой примерчик приложите так сказать продемонстрировать преимущество подхода.
Если уже ничего не помогает - прочти инструкцию.
sysinstall - гадость :)
ASUS A6q00Vm Pentium-M 1.7 GHz, 2Gb RAM, 160Gb HDD,
GeForce Go 7300 64Mb video
sysinstall - гадость :)
ASUS A6q00Vm Pentium-M 1.7 GHz, 2Gb RAM, 160Gb HDD,
GeForce Go 7300 64Mb video
-
Satana666
- Сообщения: 4
- ОС: В поиске подходящей ОС!
Re: C++ в Linux: пайпы
Разделяемая память не катит, ибо нужно сделать на пайпах! (Учусь с Xaktyc)
-
Xaktyc
- Сообщения: 604
- ОС: Gentoo 2008.0, WinXP
Re: C++ в Linux: пайпы
Если я не ошибаюсь, первый мой вариант был через подобие разделенки
Но от нас требуют файлы и пайпы (ну по программе изучения) - файлы я сделал, надо пайпы.
-
Satana666
- Сообщения: 4
- ОС: В поиске подходящей ОС!
Re: C++ в Linux: пайпы
Вот "Быдлокод" который я написал... Помогите исправить!
В пайп вроде пишет но непонятно что. Похоже что главный процесс не дожидается пока форки запишут данные в пайп.
В пайп вроде пишет но непонятно что. Похоже что главный процесс не дожидается пока форки запишут данные в пайп.
Код: Выделить всё
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
int main(int argv, char *argc[])
{
int n,k;
int faktN,faktK,pow;
int fd1[2],fd2[2],fd3[2];
n=atoi(argc[1]);
k=atoi(argc[2]);
int pr1,pr2,pr3;
pr1=fork();
if(pr1==0)
{
pipe(fd1);
dup2(fd1[1],1);
execl("fakt",argc[1]);
close(fd1[1]);
}
pr2=fork();
if (pr2==0)
{
pipe(fd2);
dup2(fd2[1],1);
execl("fakt",argc[2]);
close(fd2[1]);
}
pr3=fork();
if (pr3==0)
{
pipe (fd3);
dup2(fd3[1],1);
execl("pow",argc[1],argc[1],argc[2]);
close(fd3[1]);
}
char readbuffer1[50];
char readbuffer2[50];
char readbuffer3[50];
char bufN,bufK,buf_pow;
bufN=read(fd1[0], readbuffer1,sizeof( readbuffer1));
bufK=read(fd2[0],readbuffer2,sizeof( readbuffer2));
buf_pow=read(fd3[0],readbuffer3,sizeof( readbuffer3));
int rez;
faktN=atoi(bufN);
faktK=atoi(bufK);
pow=atoi(buf_pow);
rez=(faktN-faktK)/pow;
cout<<rez<<endl;
return 0;
}-
Xaktyc
- Сообщения: 604
- ОС: Gentoo 2008.0, WinXP
Re: C++ в Linux: пайпы
Нас бы интересовало как грамотно воспользоваться wait или waitpid(), разобраться не получилось пока.
-
pcodr
- Сообщения: 283
- ОС: Debian
Re: C++ в Linux: пайпы
Смотрите мой пример, там есть waitpid. Смысл такой: при завершении потомка родителю поступает сигнал SIGCHLD, у родителя должен стоять обработчик этого сигнала, а именно вызываться waitpid, который убирает завершившиеся дочерние процессы из таблицы процессов, дабы они не висели там в виде зомби.
remote system type is unix
-
Satana666
- Сообщения: 4
- ОС: В поиске подходящей ОС!
Re: C++ в Linux: пайпы
Так вот код который у нас имеется после недельного обсуждения проблемы на форумах!
Сейчас в пайпы пишет нормально. Но, возникла следующая проблема! при выводе buf1,buf2,buf3 на экране появляются непонятные кракозябры, если выводить этиже массивы после преобразования из в int, то выводит нули.
Код: Выделить всё
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
using namespace std;
int main(int argv, char *argc[])
{
int n,k;
int faktN,faktK,pow;
int fd1[2],fd2[2],fd3[2];
int pr1,pr2,pr3;
pipe(fd1);
pr1=fork();
if(pr1==0)
{
close(fd1[0]);
dup2(fd1[1],1);
execl("fakt",argc[1]);
} else
close(fd1[1]);
pipe(fd2);
pr2=fork();
if (pr2==0)
{
close(fd2[0]);
dup2(fd2[1],1);
execl("fakt",argc[2]);
}else
close(fd2[1]);
pipe(fd3);
pr3=fork();
if (pr3==0)
{
close(fd3[0]);
dup2(fd3[1],1);
execl("pow",argc[1],argc[1],argc[2]);
}else
close(fd3[0]);
char buf1[50];
char buf2[50];
char buf3[50];
read(fd1[0],buf1,sizeof(buf1));
read(fd2[0],buf2,sizeof(buf2));
read(fd3[0],buf3,sizeof(buf3));
cout<<buf1<<"------"<<buf2<<"-------"<<buf3<<endl;
float rez;
faktN=atoi(buf1);
faktK=atoi(buf2);
pow=atoi(buf3);
cout<<faktN<<"||"<<faktK<<"||"<<pow<<endl;
rez=(faktN-faktK)/pow;
cout<<rez<<endl;
return 0;
}Сейчас в пайпы пишет нормально. Но, возникла следующая проблема! при выводе buf1,buf2,buf3 на экране появляются непонятные кракозябры, если выводить этиже массивы после преобразования из в int, то выводит нули.
-
Xaktyc
- Сообщения: 604
- ОС: Gentoo 2008.0, WinXP
Re: C++ в Linux: пайпы
Это ведь еще до того, как мы все поменяли местами и начали закрывать пайпы...
Лучше бы ты попозже код с сервера выложил.
UPD:
Если это новый код, нафига отладочную инфу убрал?
-
Satana666
- Сообщения: 4
- ОС: В поиске подходящей ОС!