Je veux faire un programme simple, où un processus père crée des processus fils; avant la pause de l'enfant(), ils notifient le processus père. Les processus enfants s'exécutent correctement, mais le père attend sur select, sinon l'enfant a écrit sur socket; où est l'erreur?Programmation de socket, processus bloqué sur select?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
typedef struct{
pid_t pid;
int sockfd;
}Child;
void err_exit(char* str)
{
perror(str);
exit(EXIT_FAILURE);
}
int convert_int(char* str)
{
int v;
char*p;
errno = 0;
v = strtol(str,&p,0);
if(errno != 0 || *p != '\0')
err_exit("errno");
return v;
}
void child_job(pid_t pid,int sockfd)
{
int v = write(sockfd,"1",1);
if(v == -1)
err_exit("write");
printf("process %d in pause()\n",pid);
pause();
}
int main(int argc, char* argv[])
{
int nsel;
fd_set masterset;
int n_child,i;
int sockfd[2];
pid_t pid;
Child* c = NULL;
if(argc != 2)
err_exit("usage: <awake2> #children\n");
FD_ZERO(&masterset);
n_child = convert_int(argv[1]);
c = malloc(n_child*sizeof(Child));
if(c == NULL)
err_exit("malloc");
for(i = 0; i <n_child; i++){
if ((socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd)) < 0) { //create socket between child and father
perror("errore in socketpair");
exit(1);
}
if ((pid = fork()) > 0) {
if (close(sockfd[1]) == -1) { //father process closes sockfd[1]
perror("errore in close");
exit(1);
}
c[i].pid = pid;
c[i].sockfd = sockfd[0];
FD_SET(c[i].sockfd, &masterset);
}
else if(!pid)
child_job(getpid(),c[i].sockfd);
}
for(;;){
if ((nsel = select(n_child+1, &masterset, NULL, NULL, NULL)) < 0) {
perror("errore in bind");
exit(1);
}
int i;
for(i = 0; i <n_child; i++){
if(FD_ISSET(c[i].sockfd, &masterset)) {
printf("changed fd\n");
}
}
}
}
La raison pour laquelle select choisit le maximum fd plus 1 est que (dans l'implémentation d'origine au moins) le noyau traite le 'fd_set' comme un tableau de bits sans limite de taille inhérente. Il y a quelques implémentations où vous pouvez agrandir la définition 'fd_set' dans votre programme C si la taille par défaut n'est pas assez grande pour tous vos fd. Donc le" max fd plus 1 "indique juste où le tableau se termine. C'est exactement la même raison que 'read' prend un pointeur et une taille. Les implémentations qui n'utilisent pas un tableau de bits, ou ne permettent pas de le redimensionner, ne devraient pas vraiment avoir besoin du maxfd + 1 mais elles font partie de l'API –