Я пытаюсь реализовать некоторые IPC без мьютексов, условий и семафоров, используя только каналы. Следующий код представляет родительский процесс, разветвляющийся на 3 дочерних процесса (p11,p12,p13). Родитель пробуждает всех дочерних процессов сигналом SIGUSR2
, затем p11 начинает записывать 50 случайных чисел в конвейер. p12 и p13 конкурентно читают из конвейера и записывают полученные числа в свой собственный файл (file12 и file13). 50-е число - это -1
, как только дети читают -1, они выходят. write
, используемый в дочернем элементе p11, просто не записывает ни одного байта, он возвращает -1
. Я могу использовать только вызовы write(2)
и read(2)
для записи и чтения. У меня не получается это реализовать, пробовал несколько раз, безрезультатно. Надеюсь, вы можете мне помочь.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/wait.h>
void handler(int signo)
{
printf("\nSignal intercepted!\n");
}
void main ()
{
srand(time(NULL));
signal(SIGUSR2,handler);
int pa[2];
pipe(pa[2]); //create pipe
pid_t pid1,pid2,pid3;
if((pid1=fork())==0) //child 11
{
close(pa[0]); //close the read side of the pipe
pause();
int i,nwrite,num;
for(i=0;i<49;i++)
{
num=rand()%100+1; //generate a random number
nwrite=write(pa[1],&num,sizeof(int)); //write it to the pipe
if(nwrite==-1) //if there's a write error
{
printf("\nWrite error..\n");
exit(-1);
}
}
num=-1; //generate the last number
nwrite=(write(pa[1],&num,sizeof(int))); //write the last number to the pipe
if (nwrite==-1) //if there's a write error
{
printf("\nError,now exiting...\n");
exit(-1);
}
close(pa[1]); //close the pipe in write mode
exit(1);
}
else if ((pid2=fork())==0) //child 12
{
close(pa[1]); //close the write side of the pipe
pause();
int fd1,nread,num;
fd1=open("file12.txt",O_CREAT,0777); //create a new file
while((nread=read(pa[0],&num,sizeof(num)))>0) //while there are bytes to read
{
if(num!=-1) //if this isn't the last number
{
write(fd1,&num,sizeof(num)); //write it to the file
}
else
{
printf("\n-1 sent!\n"); //notify the last read number
close(pa[0]); //close the read side of the pipe
close(fd1); //close the file descriptor
exit(1); //exit
}
}
}
else if ((pid3=fork())==0) //child 13, same as 12
{
close(pa[1]);
pause();
int fd2,nread,num;
fd2=open("file13.txt",O_CREAT,0777);
while((nread=read(pa[0],&num,sizeof(num)))>0)
{
if(num!=-1)
{
write(fd2,&num,sizeof(num));
}
else
{
printf("\n-1 sent!\n");
close(pa[0]);
close(fd2);
exit(1);
}
}
}
else //parent
{
sleep(1);
kill(pid1,SIGUSR2); //wake up all the childs
kill(pid2,SIGUSR2);
kill(pid3,SIGUSR2);
waitpid(pid1,0,NULL); //wait for the childs to end
waitpid(pid2,0,NULL);
waitpid(pid3,0,NULL);
printf("\nDone, now exiting...\n"); //exit
}
}
pipe(pa[2]);
? - person alk   schedule 01.07.2016printf("\nWrite error..\n");
наperror("write() failed");
- person alk   schedule 01.07.2016printf()
нет. Читайте здесь pubs.opengroup.org/onlinepubs/9699919799/functions/, чтобы найти список функций, которые можно использовать из обработчиков сигналов. - person alk   schedule 01.07.2016signo
), то первая строка в теле функции должна быть:(void)signo;
При компиляции всегда включайте все предупреждения, а затем исправьте эти предупреждения. Среди МНОГИХ других проблем есть только две действительные подписи дляmain()
1)int main( void )
2)int main( int, char ** )
IE. возвращаемый тип изmain()
всегдаint
- person user3629249   schedule 02.07.2016fork()
имеет три вида возвращаемых значений: ‹0 при возникновении ошибки, ==0 при выполнении дочернего процесса, ›0 при выполнении родительского процесса. Опубликованный код не обрабатывает состояние ошибки - person user3629249   schedule 02.07.2016time()
возвращаетtime_t
, однако функцияsrand()
ожидает параметрunsigned int
, чтобы избежать предупреждений компилятора, преобразуйте возвращаемое значение изtime()
вunsigned int
. - person user3629249   schedule 02.07.2016gcc
при минимальном использовании:-Wall -Wextra -pedantic
также использую:-Wconversion -std-gnu99
) - person user3629249   schedule 02.07.2016write()
возвращаетssize_t
, а неint
. Функцияread()
возвращаетssize_t
, а неint
- person user3629249   schedule 02.07.2016waitpid()
— это иint
, а не указатель, поэтому третий параметр должен быть равен 0, а не NULL. - person user3629249   schedule 02.07.2016nwrite=(write(pa[1],&num,sizeof(int)));
дополнительный набор скобок просто загромождает код, делая его намного более трудным для понимания, отладки и обслуживания. Предложите удалить внешний набор скобок. - person user3629249   schedule 02.07.2016open()
) всегда проверяйте возвращаемое значение, чтобы убедиться, что функция выполнена успешно, прежде чем использовать результаты вызова этой функции. - person user3629249   schedule 02.07.2016