0

I have found discussion on using callbacks in AIO asynchronous I/O on the internet. However, what I have found has left me confused. An example code is listed below from a site on Linux AIO. In this code, AIO is being used to read in the contents of a file. My problem is that it seems to me that a code that actually processes the contents of that file must have some point where some kind of block is made to the execution until the read is completed. This code here has no block like that at all. I was expecting to see some kind of call analogous to pthread_mutex_lock in pthread programming. I suppose I could put in a dummy loop after the aio_read() call that would block execution until the read is completed. But that puts me right back to the simplest way of blocking the execution, and then I don't see what is gained by all the coding overhead that goes into establishing a callback. I am obviously missing something. Could someone tell me what it is?

Here is the code. (BTW, the original is in C++; I have adapted it to C.)

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <aio.h>
//#include <bits/stdc++.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>

const int BUFSIZE = 1024;




void aio_completion_handler(sigval_t sigval)
{
    struct aiocb *req;

    req = (struct aiocb *)sigval.sival_ptr; //Pay attention here.
    /*Check again if the asynchrony is complete?*/
    if (aio_error(req) == 0)
    {
        int ret = aio_return(req);
        printf("ret == %d\n", ret);
        printf("%s\n", (char *)req->aio_buf);
    }
    close(req->aio_fildes);
    free((void *)req->aio_buf);
    while (1)
    {
        printf("The callback function is being executed...\n");
        sleep(1);
    }
}



int main(void)
{
    struct aiocb my_aiocb;
    int fd = open("file.txt", O_RDONLY);
    if (fd < 0)
        perror("open");
    bzero((char *)&my_aiocb, sizeof(my_aiocb));

    my_aiocb.aio_buf = malloc(BUFSIZE);
    if (!my_aiocb.aio_buf)
        perror("my_aiocb.aio_buf");

    my_aiocb.aio_fildes = fd;
    my_aiocb.aio_nbytes = BUFSIZE;
    my_aiocb.aio_offset = 0;

    //Fill in callback information
    /*
    Using SIGEV_THREAD to request a thread callback function as a notification method
    */
    my_aiocb.aio_sigevent.sigev_notify = SIGEV_THREAD;
    my_aiocb.aio_sigevent.sigev_notify_function = aio_completion_handler;
    my_aiocb.aio_sigevent.sigev_notify_attributes = NULL;
    /*
    The context to be transmitted is loaded into the handler (in this case, a reference to the aiocb request itself).
    In this handler, we simply refer to the arrived sigval pointer and use the AIO function to verify that the request has been completed.
    */
    my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb;

    int ret = aio_read(&my_aiocb);
    if (ret < 0)
        perror("aio_read");
    /*    <---- A real code would process the data read from the file.
     *          So execution needs to be blocked until it is clear that the
     *          read is complete.  Right here I could put in:
     *          while (aio_error(%my_aiocb) == EINPROGRESS) {}
     *          But is there some other way involving a callback?
     *          If not, what has creating a callback done for me?
     */
    //The calling process continues to execute
    while (1)
    {
        printf("The main thread continues to execute...\n");
        sleep(1);
    }
    return 0;
}
bob.sacamento
  • 6,283
  • 10
  • 56
  • 115
  • Code such as `printf("%s\n", (char *)req->aio_buf);` is a poor mix with calls like `aio_read()` **that don't terminate buffers with a `'\0'` character**. – Andrew Henle Dec 09 '20 at 17:22
  • Using aio and a callback is only useful if your process has something else to do instead of waiting for the I/O. I've used it for realtime audio where reads happen in the background while the foreground is processing the data. – stark Dec 09 '20 at 19:54
  • @stark Yes, thanks. I do understand that. But I still don't know how to make it work. Do you have an example that could be shared here? Thanks. – bob.sacamento Dec 09 '20 at 21:05
  • Just to be totally clear here, this is not Linux AIO. What you have above is POSIX AIO, which spawns threads to do asynchronous I/O. Linux AIO uses `io_submit` and `io_getevents`, and does not require threading - perhaps that's what you're looking for? – Mike Andrews Dec 10 '20 at 22:20

0 Answers0