Jump to content
black_death_c4t

[C] Unix - Pipe & Fifo

Recommended Posts

Cerinta suna cam asa:

Se cere un server si unul sau mai multi clienti.

Fiecare client trimite catre server un nume de fisier text.

Serverul citeste continutul fisierului si ii intoarce clientului

primele trei linii in ordine alfabetica din cadrul fisierului.

Ma gandeam sa trimit de la client prin pipe o comanda de shell preconstruita de mine , serverul sa o execute si sa trimit inapoi catre client output-ul comenzii executate

Ce am lucrat eu aiurea pana acu:

[C] ----client.c----- /* Se cere un server si unul sau mai multi clienti. Fiec - Pastebin.com

E vorba de comunicare intre procese :)

Anyone got any ideas ? I suck at programming .

Edited by black_death_c4t
Link to comment
Share on other sites

Cea mai mare prostie, sa folosesti ditamai libraria, mai ales pentru un proiect de 20 de linii de cod.

black_death_c4t Deci care e problema?

"Se cere un server si unul sau mai multi clienti." - Nu e server pe TCP?

Nu , e vorba de comunicare intre procesele aceluiasi sistem fizic , rularea serverului si clientului fiind facuta fiecare intr-un terminal . Am nevoie de o implementare pentru un singur client : clientul trimite la server informatia , serverul o citeste si ii returneaza alta dracie / over.

http://www.cs.ubbcluj.ro/~dadi/so1/Lab10/documentation.html

http://www.cs.ubbcluj.ro/~dadi/so1/Lab10/example.html

http://www.cs.ubbcluj.ro/~florin/SO/ExempleSurseDocumentatii/C/PipeFifoMesShmSem/SO_UPipe-H.txt

Edited by black_death_c4t
Link to comment
Share on other sites

Un exemplu asemanator:

/*
* Parintele trimite procesului fiu prin pipe numele unui fisier,
* iar procesul fiu va returna catre parinte primele 10 caractere
* din fisierul text solicitat.
*/


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


int main()
{
int fd[2];
FILE* fp;
pid_t childpid;
char string[50];
char ch;
char readbuffer[50];



pipe(fd);


if ((childpid = fork()) == -1)
{
perror("fork");
exit(1);
}


if (childpid == 0) //child
{
close(fd[1]);
read(fd[0], readbuffer, sizeof(readbuffer));

fp = fopen(readbuffer, "r");
int i;
for (i=0;i<=9;i++)
{
ch = fgetc(fp);
printf("%c",ch);
}
fclose(fp);
}
else //parent
{
printf("Dati calea fisierului: ");
gets(string);
close(fd[0]);
write(fd[1], string, strlen(string)+1);
}
printf("\n");
return 0;
}

Sau:Clientul ii transmite serverului un nume de fisier iar serverul intoarce clientului numarul de linii din fisierul respectiv.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int _, char**$) //se da ca parametru ruta fisierului in cauza
{
int P[2];
pipe(P);
write(P[1], $[1], strlen($[1])+1);

if (!fork())
{
char fbuffer[255];
read(P[0], fbuffer, sizeof(fbuffer));
FILE* f=fopen(fbuffer,"r");
char c;_=1;
while (c != EOF)if((c=getc(f))=='\n')_++;
fclose(f);
write(P[1],&_,sizeof(_));
}else{
wait(0);
read(P[0], &_,sizeof(_));
printf("%d\n",_);
close(P[0]);
close(P[1]);
}
return 0;
}

Link to comment
Share on other sites

Ai noroc ca nu aveam somn azi-noapte.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>




#define SV 1
#define CL 2


#define BUFL 128


#define check(a, !strcmp(a,




static inline int str_comp(const void * first, const void * second)
{
return strcmp(*((char * *)first), *((char * *)second));
}




void process_file(char * fname, char * lines)
{
/* open the file, read and sort all lines,
then write the first 3 of them to `lines` buffer */


int linesLen = 0;
char * * linesVec = NULL;


FILE * file = fopen(fname, "r");
while (1) {
char line[BUFL];
fgets(line, BUFL, file);
if (feof(file))
break;


linesVec = realloc(linesVec, ++linesLen * sizeof(char *));
linesVec[linesLen - 1] = malloc((strlen(line) + 1) * sizeof(char));
strcpy(linesVec[linesLen - 1], line);
}
fclose(file);


qsort(linesVec, linesLen, sizeof(char *), str_comp);

strcpy(lines, linesVec[0]);
strcat(lines, linesVec[1]);
strcat(lines, linesVec[2]);


for (int i = 0; i < linesLen; ++i)
free(linesVec[i]);
free(linesVec);
}




int main(int argc, char * argv[])
{
if (argc < 3) {
printf("Usage: %s OPTION (NAME...|NAME FILE)\n", argv[0]);
puts("Open a server or client using named pipes communication for processing a file.\n\
\n\
Options:\n\
-s, --server open for serving\n\
-c, --client open for sending\n\
\n\
Parameters:\n\
NAME path name(s) for FIFO(s)\n\
FILE file path for lines reading");
return 1;
}


int whoami = 0;
if (check(argv[1], "-s") || check(argv[1], "--server"))
whoami = SV;
else if (check(argv[1], "-c") || check(argv[1], "--client"))
whoami = CL;


if (whoami == SV) {
// make FIFOs
int fifoLen = argc - 2;
// for input/output
char * * fifoIn = malloc(sizeof(char *) * fifoLen);
char * * fifoOut = malloc(sizeof(char *) * fifoLen);


for (int i = 2; i < 2 + fifoLen; ++i) {
int ind = i - 2;
int len = sizeof(char) * (strlen(argv[i]) + 2);
fifoIn[ind] = malloc(len);
fifoOut[ind] = malloc(len);

strcpy(fifoIn[ind], argv[i]);
strcpy(fifoOut[ind], argv[i]);
strcat(fifoIn[ind], "i");
strcat(fifoOut[ind], "o");


// rw-rw-rw-
mkfifo(fifoIn[ind], 0666);
mkfifo(fifoOut[ind], 0666);


}


// wait for messages, process them, then send the response
for (int i = 0; i < fifoLen; ++i) {
pid_t pid = fork();
if (pid == 0) {
// the child


// open the pipe for reading
int fin = open(fifoIn[i], O_RDONLY);
char fname[BUFL] = {0};
read(fin, fname, BUFL);
close(fin);


// read the filename, open and process it
printf("Process %s on channel %s\n", fname, argv[i + 2]);
char lines[3 * BUFL] = {0};
process_file(fname, lines);


// send the lines back to client
int fout = open(fifoOut[i], O_WRONLY);
write(fout, lines, strlen(lines));
close(fout);


return 0;
}
}
// wait processes to finish
for (int i = 0; i < fifoLen; ++i)
wait(NULL);


// free resources
for (int i = 0; i < fifoLen; ++i) {
unlink(fifoIn[i]);
unlink(fifoOut[i]);
free(fifoIn[i]);
free(fifoOut[i]);
}
free(fifoIn);
free(fifoOut);
} else if (whoami == CL) {
// prepare pipe names for i/o
int len = sizeof(char) * (strlen(argv[2]) + 2);
char * fifoIn = malloc(len);
char * fifoOut = malloc(len);
strcpy(fifoIn, argv[2]);
strcat(fifoIn, "i");
strcpy(fifoOut, argv[2]);
strcat(fifoOut, "o");


// open server's input for writing
int fout = open(fifoIn, O_WRONLY);
write(fout, argv[3], strlen(argv[3]));
close(fout);


// now receive the response
int fin = open(fifoOut, O_RDONLY);
char lines[3 * BUFL] = {0};
read(fin, lines, 3 * BUFL);
close(fin);


puts(lines);


free(fifoIn);
free(fifoOut);
} else {
fputs("Invalid or no option selected\n", stderr);
return 2;
}


return 0;
}

Edited by cmiN
  • Upvote 1
Link to comment
Share on other sites

meh , se multumeste foarte mult ; intre timp a reusit si creierul meu aproape inutil sa produca ceva aproape folositor

http://pastebin.com/pTbkEGk6

As aprecia daca s-ar uita cineva 2 secunde peste cod , specific la partea in eu transmit prin pipe comanda shell catre server , deoarece , desi fac read(x,x,KKT*sizeof(char)) se citeste doar pana la primul spatiu .

Prin KKT ma refer la strlen() de lungimea comenzii initial formate in client ( e undeva pe la 21 de caractere "head -n 3 fisier.txt | sort "). N-am reusit sa descopar de ce se intampla asta asa ca am inlocuit comanda aia mai lunga cu o comanda simpla gen "who" si am verificat daca sistemul client-server functioneaza corespunzator.

Edited by black_death_c4t
Link to comment
Share on other sites

meh , se multumeste foarte mult ; intre timp a reusit si creierul meu aproape inutil sa produca ceva aproape folositor

[C] //clientul --- /* Se cere un server si unul sau mai multi clienti. Fiecare cl - Pastebin.com

As aprecia daca s-ar uita cineva 2 secunde peste cod , specific la partea in eu transmit prin pipe comanda shell catre server , deoarece , desi fac read(x,x,KKT*sizeof(char)) se citeste doar pana la primul spatiu .

Prin KKT ma refer la strlen() de lungimea comenzii initial formate in client ( e undeva pe la 21 de caractere "head -n 3 fisier.txt | sort "). N-am reusit sa descopar de ce se intampla asta asa ca am inlocuit comanda aia mai lunga cu o comanda simpla gen "who" si am verificat daca sistemul client-server functioneaza corespunzator.

Este posibil ca in argv[1] sa ai string termination (\0) sau prioritatea executiilor intre paranteze sa fie gresita?

Enuntul problemei pentru acest laborator incepe cu:

"Se cere un server si unul sau mai multi clienti"

Sunt curios aici cu ce solutii ati veni pentru a preveni deadlock si a face sincronizare intre childs si parent. O alta abordare ar fi un socket (tcp/udp) sau fisier de tip fifo pe sistemul de fisiere.

Edited by fedorffixxzz
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...