Bonjour amis inpactiens,
Je m'essaye a la programmation C posix et je me pose une petite question enfin surtout je rencontre un probleme :)
Je viens de faire un petit programme simple qui se resume à :
- Forker un processus.
- Ouvrir un pipe dans le processus parent qui envoie des données dans le processus enfant.
- Ouvrir un pipe dans le processus enfant qui renvoie les données transmise en majuscule (traitement simple de caracteres).
Afin de faire ca propre la legende posixienne voudrait que je fasse un select dans le processus parent pour switcher entre le moment d'envoyer les données dans le processus enfant et le moment d'ecrire les données sur STDOUT recu du processus enfant.
Mon petit programme sans le select marche actuellement comme ca :
http://pastebin.com/708367
(désoler obliger de prendre pastebin le forum meme avec les balise code et pre tiens absolument a me urlencode et c'est génant)
Ca marche mais a mon avis je risque des deadlock lors de gros flux de données, comme vous pouvez le voir j'ai commencé a déclarer ma struct pour le select mais je bloque un peu. La légende raconte :
* Fill up a fd_set structure with the file descriptors you want to know when data comes in on.
* Fill up a fd_set structure with the file descriptors you want to know when you can write on.
Mais eu concretement comment mettre ca en place dans ce genre de situation ?
Merci de votre aide qui me sera surement d'un grand secours !
# Details
Posté par peck (site web personnel) . Évalué à 3.
Ensuite tu n'as potentiellement un probleme que si tu comptes envoyer plus de données qu'en recevoir : 512 -> MAXBUFFER
Mais sinon sur le principe, le read est bloquant et tu lis un seul fd a la fois, donc tu n'as pas besoin de select dans ce cas précis.
[^] # Re: Details
Posté par Sylvain (site web personnel) . Évalué à 1.
Et dans cet exemple que j'ai ecrit cela me permettrait de le comprendre facilement !
Merci de ton aide :p
[^] # Re: Details
Posté par JaguarWan . Évalué à 2.
/* gcc -W -Wall -std=c99 -posix -pedantic posix.c */
#define _BSD_SOURCE
#define _ISOC99_SOURCE
#include <stdlib.h> /* libc */
#include <unistd.h> /* pipe(), fork(), *_FILENO ... */
#include <stdio.h> /* printf(), BUFSIZ, ... */
#include <ctype.h> /* toupper() */
#include <string.h> /* memset() */
#include <sys/types.h> /* pid_t, ... */
#include <sys/wait.h>
#define STRINGIFY(x) #x
#define STR(x) STRINGIFY(x)
#define ERR(c, f) #c "()::" #f "() @ " __FILE__ ":" STR(__LINE__)
static inline void _strtoupper(char *s)
{
do *s = toupper(*s); while (*s ++);
}
int main(void)
{
pid_t pid = 0;
char buf[BUFSIZ]; /* buffer de lecture */
int in[2], out[2]; /* les pipes */
fd_set fd;
struct timeval tmout;
int run = 20; /* nombre de tours */
int len = 0; /* retour de read */
/* ouvre les pipe d'input/output */
if (pipe(in) == -1) {
perror(ERR(main, pipe)); exit(EXIT_FAILURE);
}
if (pipe(out) == -1) {
perror(ERR(main, pipe)); exit(EXIT_FAILURE);
}
/* pipe[0] = lecture, pipe[1] = ecriture */
switch ( (pid = fork()) ) {
case -1: /* failed */
close(in[0]); close(in[1]);
close(out[0]); close(out[1]);
exit(EXIT_FAILURE);
case 0: /* papa */
/* on veut ecrire dans l'input, et lire dans l'output (point de vue fiston) */
close(in[0]); close(out[1]);
if (dup2(out[0], STDIN_FILENO) == -1) {
perror(ERR(main, dup2)); exit(EXIT_FAILURE);
}
if (dup2(in[1], STDOUT_FILENO) == -1) {
perror(ERR(main, dup2)); exit(EXIT_FAILURE);
}
/* ecrit un message d'initialisation au bout de cinq secondes */
sleep(5);
printf("salut fiston !");
fflush(stdout);
break;
default: /* fiston */
/* on veut lire dans l'input, et ecrire dans l'output */
close(in[1]); close(out[0]);
if (dup2(in[0], STDIN_FILENO) == -1) {
perror(ERR(main, dup2)); exit(EXIT_FAILURE);
}
if (dup2(out[1], STDOUT_FILENO) == -1) {
perror(ERR(main, dup2)); exit(EXIT_FAILURE);
}
}
/* boucle de lecture/ecriture commune */
while (run --) {
/* une seconde de timeout */
tmout.tv_sec = 1;
tmout.tv_usec = 0;
/* c'est pas portable de faire ca avec le vrai stdin, mais la c'est notre pipe */
FD_SET(STDIN_FILENO, & fd);
if (select(1, & fd, NULL, NULL, & tmout) == -1) {
perror(ERR(main, select)); exit(EXIT_FAILURE);
}
if (FD_ISSET(STDIN_FILENO, & fd)) {
memset(buf, '\0', sizeof(buf));
if ( (len = read(STDIN_FILENO, buf, sizeof(buf))) == -1) {
perror(ERR(main, read)); exit(EXIT_FAILURE);
}
if (len == 0) {
fprintf(stderr, "%s: connection morte\n", (pid) ? "fiston" : "papa");
break;
}
if (pid == 0) {
/* papa */
fprintf(stderr, "Le fiston a ecrit: %s\n", buf);
printf("met-moi ca en caps fiston...");
fflush(stdout);
} else {
/* fiston */
_strtoupper(buf);
printf("%s", buf);
fflush(stdout);
}
} else {
fprintf(stderr, "%s: j'ai rien a faire !\n", (pid) ? "fiston" : "papa");
}
}
/* normalement le fils creve toujours avant, mais soyons propre */
if (pid == 0) wait(NULL);
/* vu qu'on a branche les pipe sur stdin/out, cleanup automatique */
exit(EXIT_SUCCESS);
}
[^] # Re: Details
Posté par JaguarWan . Évalué à 2.
static inline void _strtoupper(char *s, size_t len)
{
if (! s || ! len) return;
while (len --) s[len] = toupper(s[len]);
}
en utilisant la longueur renvoyée par read(2)...
/!\ le paramètre len revient à strlen() + 1 là (read(2) compte le NUL final)
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.