aio_read d'erreur de fichier sur OS X
Question
Le code suivant:
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <aio.h>
#include <errno.h>
int main (int argc, char const *argv[])
{
char name[] = "abc";
int fdes;
if ((fdes = open(name, O_RDWR | O_CREAT, 0600 )) < 0)
printf("%d, create file", errno);
int buffer[] = {0, 1, 2, 3, 4, 5};
if (write(fdes, &buffer, sizeof(buffer)) == 0){
printf("writerr\n");
}
struct aiocb aio;
int n = 2;
while (n--){
aio.aio_reqprio = 0;
aio.aio_fildes = fdes;
aio.aio_offset = sizeof(int);
aio.aio_sigevent.sigev_notify = SIGEV_NONE;
int buffer2;
aio.aio_buf = &buffer2;
aio.aio_nbytes = sizeof(buffer2);
if (aio_read(&aio) != 0){
printf("%d, readerr\n", errno);
}else{
const struct aiocb *aio_l[] = {&aio};
if (aio_suspend(aio_l, 1, 0) != 0){
printf("%d, suspenderr\n", errno);
}else{
printf("%d\n", *(int *)aio.aio_buf);
}
}
}
return 0;
}
fonctionne très bien sous Linux (Ubuntu 9.10, compilé avec -lrt), l'impression
1
1
Mais échoue sur OS X (10.6.6 et 10.6.5, je l'ai testé sur deux machines):
1
35, readerr
Est-ce possible que cela est dû à une erreur sur la bibliothèque OS X, ou que je fais quelque chose de mal?
La solution
Vous devez appeler aio_return(2)
exactement une fois pour chaque opération d'E / S asynchrone. D'après la note sur cette page de manuel, défaut de le faire fuira les ressources, et il provoque apparemment aussi votre problème. Une fois que vous appelez aio_suspend
attendre le E / S complète, assurez-vous de aio_return
d'appel pour obtenir le nombre d'octets lus, par exemple:.
const struct aiocb *aio_l[] = {&aio};
if (aio_suspend(aio_l, 1, 0) != 0)
{
printf("aio_suspend: %s\n", strerror(errno));
}
else
{
printf("successfully read %d bytes\n", (int)aio_return(&aio));
printf("%d\n", *(int *)aio.aio_buf);
}
Gardez aussi à l'esprit ces remarques importantes de la aio_read(2)
de l'homme (Souligné par l'auteur):
La structure de contrôle E / S asynchrones Bloquer pointé par
aiocbp
et la tampon que l'élément deaiocbp->aio_buf
de cette structure références doivent restent valables jusqu'à ce que l'opération soit terminée. Pour cette raison, l'utilisation variables automatiques (de la pile) pour ces objets est déconseillée .Le tampon asynchrone de commande I / O
aiocbp
doit être mis à zéro avant la appelaio_read()
pour éviter de transmettre des informations contextuelles bogus au noyau.
Autres conseils
Essayez la mise à zéro struct aiocb aio
?
Le manuel se lit comme suit:
RESTRICTIONS
[...]
The asynchronous I/O control buffer aiocbp should be zeroed before the
aio_read() call to avoid passing bogus context information to the kernel.
[...]
BUGS
Invalid information in aiocbp->_aiocb_private may confuse the kernel.