Pour 'daemonizer' le processus courant, j'utilise ce bout de code (le boolean en paramètre sert à indiquer si on doit faire un double fork ou pas -- en pratique, si tu le lances pas avec init faut le mettre à true):
Sinon, pour ta boucle de lecture de fichier, tu pourrais utiliser fread/fwrite, ou mapper le fichier en mémoire, ou encore (dans ton premier post tu compte utiliser un socket) utiliser un socket, et la super fonction sendfile() :)
/* récupère la taille du fichier à balancer */
if (fstat(in, & infos) == -1)
perror(ERR(lecture, fstat));
else
/* on récupère juste la taille, mais on pourrait vérifier
* que c'est bien un fichier régulier, toussa...
*/
taille_fichier = infos.st_size;
/* mappe le fichier en mémoire (gros tableau) */
if ( (map = mmap(NULL, taille_fichier, PROT_READ, MAP_PRIVATE, in, 0) == MAP_FAILED) {
perror(ERR(lecture, mmap)); abort();
}
/* oh le gros write de bourrin :) */
write(fd, map, taille_fichier);
[Coller ici le même code que pour mmap, mais sans ouvrir lp]
au lieu d'appeler mmap(), et en supposant que tu as un socket connecté à ton imprimante nommé 'bull':
ssize_t ret = 0;
if ( (ret = sendfile(bull, in, NULL, taille_fichier)) == -1)
perror(ERR(lecture, sendfile));
else
printf("youpi, sendfile a envoyé %z bytes dans les tuyaux\n", ret);
# Bout de code
Posté par JaguarWan . En réponse au message Programmer un outil d'impression.... Évalué à 3.
------------------------------8<--------------------------------
static void daemonize(int dofork)
{
/** @brief This daemonizes the current process */
pid_t pid;
struct rlimit limit;
/* Set to background */
if (dofork || getppid() != 1)
{
pid = fork();
switch(pid)
{
case -1: /* Error */
perror(ERR(daemonize, fork)); exit(1);
break;
case 0: /* Success */
break;
default: /* Kill the father */
exit(0);
}
/* Run the processus in a new session */
setpgid(0, 0);
pid = fork();
switch(pid)
{
case -1: /* Error */
perror(ERR(daemonize, fork)); exit(1);
break;
case 0: /* Success */
break;
default: /* Kill the father */
exit(0);
}
/* Ignore terminal signals */
if (signal(SIGTTIN, SIG_IGN) == SIG_ERR)
{
perror(ERR(daemonize, signal)); exit(1);
}
if (signal(SIGTTOU, SIG_IGN) == SIG_ERR)
{
perror(ERR(daemonize, signal)); exit(1);
}
if (signal(SIGTSTP, SIG_IGN) == SIG_ERR)
{
perror(ERR(daemonize, signal)); exit(1);
}
if (signal(SIGCHLD, SIG_IGN) == SIG_ERR)
{
perror(ERR(daemonize, signal)); exit(1);
}
}
/* Change directory to root */
if (chdir("/") != 0) { perror(ERR(daemonize, chdir)); exit(1); }
/* Get the maximum file descriptor */
if(getrlimit(RLIMIT_NOFILE, & limit) == -1)
{
perror(ERR(daemonize, getrlimit)); exit(1);
}
/* Close all the file descriptors */
while (limit.rlim_cur --) { close(limit.rlim_cur); }
}
------------------------------8<--------------------------------
Sinon, pour ta boucle de lecture de fichier, tu pourrais utiliser fread/fwrite, ou mapper le fichier en mémoire, ou encore (dans ton premier post tu compte utiliser un socket) utiliser un socket, et la super fonction sendfile() :)
Exemples basiques:
avec fread/frwrite, ça donne ça:
------------------------------8<--------------------------------
unsigned char buffer[BUFSIZ];
for ( ;; ) {
fread(buffer, sizeof(char), sizeof(buffer), in);
if (! feof)
fwrite(buffer, sizeof(char), sizeof(buffer), fp);
else
break;
}
------------------------------8<--------------------------------
mais c'est un euphémisme de dire que c'est pas optimal :)
exemple naïf avec mmap():
------------------------------8<--------------------------------
unsigned char *map = NULL;
int in = 0;
int lp = 0;
struct stat infos;
size_t taille_fichier = 0;
if ( (in = open(ton_fichier, O_RDONLY)) == -1) {
perror(ERR(lecture, open)); abort(); /* gestion d'erreur basique :] */
}
if ( (lp = open(imprimante, O_WRONLY)) == -1) {
perror(ERR(lecture, open)); abort(); /* gestion d'erreur basique :] */
}
/* récupère la taille du fichier à balancer */
if (fstat(in, & infos) == -1)
perror(ERR(lecture, fstat));
else
/* on récupère juste la taille, mais on pourrait vérifier
* que c'est bien un fichier régulier, toussa...
*/
taille_fichier = infos.st_size;
/* mappe le fichier en mémoire (gros tableau) */
if ( (map = mmap(NULL, taille_fichier, PROT_READ, MAP_PRIVATE, in, 0) == MAP_FAILED) {
perror(ERR(lecture, mmap)); abort();
}
/* oh le gros write de bourrin :) */
write(fd, map, taille_fichier);
------------------------------8<--------------------------------
Et le must, le gros sendfile() de sauvage, ultra pas portable mais si bourrin :)
------------------------------8<--------------------------------
[Coller ici le même code que pour mmap, mais sans ouvrir lp]
au lieu d'appeler mmap(), et en supposant que tu as un socket connecté à ton imprimante nommé 'bull':
ssize_t ret = 0;
if ( (ret = sendfile(bull, in, NULL, taille_fichier)) == -1)
perror(ERR(lecture, sendfile));
else
printf("youpi, sendfile a envoyé %z bytes dans les tuyaux\n", ret);
------------------------------8<--------------------------------
Et là, enjoy, c'est le noyau qui se tape tout le boulot, et en zero-copy s'il vous plaît :)
* la macro ERR() qui apparait un peu partout c'est un truc maison pour afficher la ligne du code qui foire:
#define STRINGIFY(x) #x
#define STR(x) STRINGIFY(x)
#define ERR(c, f) #c "()::" #f "() @ " __FILE__ ":" STR(__LINE__)
Voilà voilà :)