Callbacks in AIO asynchronous I/O - c

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;
}

Related

How could i send a message to another program, and output that it has been received?

In contiki, i need to have two files, sender and receiver, the sender sends packets to the receiver. My problem is, the receiver is not outputting that the packets have been received.
I tried a while loop inside the receiving packet, i even tried to create a function, but still nothing has worked.
My sender.c file
#include "contiki.h"
#include "net/rime.h"
#include "random.h"
#include "dev/button-sensor.h"
#include "dev/leds.h"
#include <stdio.h>
PROCESS(sendReceive, "Hello There");
AUTOSTART_PROCESSES(&sendReceive);
PROCESS_THREAD(sendReceive, ev, data)
{
PROCESS_BEGIN();
static struct abc_conn abc;
static struct etimer et;
static const struct abc_callbacks abc_call;
PROCESS_EXITHANDLER(abc_close(&abc);)
abc_open(&abc, 128, &abc_call);
while(1)
{
/* Delay 2-4 seconds */
etimer_set(&et, CLOCK_SECOND * 2 + random_rand() % (CLOCK_SECOND * 2));
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
packetbuf_copyfrom("Hello", 6);
abc_send(&abc);
printf("Message sent\n");
}
PROCESS_END();
}
my receiver.c file
#include "contiki.h"
#include "net/rime.h"
#include "random.h"
#include "dev/button-sensor.h"
#include "dev/leds.h"
#include <stdio.h>
PROCESS(sendReceive, "Receiving Message");
AUTOSTART_PROCESSES(&sendReceive);
PROCESS_THREAD(sendReceive, ev, data)
{
PROCESS_BEGIN();
{
printf("Message received '%s'\n", (char *)packetbuf_dataptr());
}
PROCESS_END();
}
The sender.c file is working, it is sending the packets correctly, the problem is the receiver seems not to output that it has been received.
While sending is simple - you just need to call a function -, receiving data in embedded system is in general more complicated. There needs to be a way for the operating system to let your code know that new data has arrived from outside. In Contiki that is internally done with events, and from user's perspective with callbacks.
So, implement a callback function:
static void
recv_from_abc(struct abc_conn *bc)
{
printf("Message received '%s'\n", (char *)packetbuf_dataptr());
}
In your receiver process, create and open an connection, passing the callback function's pointer as a parameter:
static struct abc_conn c;
static const struct abc_callbacks callbacks =
{recv_from_abc, NULL};
uint16_t channel = 128; /* matching the sender code */
abc_open(&c, channel, &callbacks);

Check if microphone is already being used with C on Linux

I was playing around with the Pulseaudio API and due to my little knowledge on how the sound system works, I'm not really understanding why it's possible having multiple applications using the mic at the same time.
Or to better phrase it: why the fprintf is not called I have 2 applications that are actively recording stuffs and I start the following program?
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <pulse/simple.h>
#include <pulse/error.h>
#define BUFSIZE 1024
int main(int argc, char*argv[]) {
/* The sample type to use */
static const pa_sample_spec ss = {
.format = PA_SAMPLE_S16LE,
.rate = 44100,
.channels = 2
};
pa_simple *s = NULL;
int ret = 1;
int error;
/* Create the recording stream */
if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error)))
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
return 0;
}
I'd guess you're not getting an error message because the program is successfully creating a pa_simple connection to the pulse audio server.
You may wish to add pa_simple_free(s); to the end of your main() before you return.
Also, here is a link to an example pa_simple record program:parec-simple_8c-example
See Pulse Audio API at freedesktop.org
EDIT: Your question "why the fprintf is not called" is because the Pulse Audio Simple API doesn't guarantee exclusive access to the Microphone. Therefor, when two other applications are already "using" the microphone, and you create a simple stream connection to the server, there is no error generated. Is your question really "How to determine if the microphone is being used by any program - and which one"?

C-library invoking a kdb function from a BG-thread

I have an external C-library for asynchronously consuming data via callback functions on a background thread; I want to receive the data and process it in a q process. Following code.kx.com's Interfacing with C documentation, I made a small C-library of glue code converting the inbound source data into k structures and dispatching it to my q process vi sd1/sd0 calls so that the q function gets invoked on q's thread context. The program successfully invokes the initial callback then hangs.
I've stripped down the program to what I think is the bare minimum to simply demonstrate a C BG-thread callback into a q function, but I'm not sure if I've stripped away too much. For example, sd1 accepts a FD and a C-callback. My bare minimum FD is created via eventfd(), which is used for subsequent sd1/sd0 calls. I have tried invoking read and write on the FD, and not doing any IO over the FD, either way the program hangs.
Here's my bare-bones C-library:
/* testlib.c */
#define KXVER 3
#include "k.h"
#include <pthread.h>
#include <sys/eventfd.h>
I d;
pthread_t tid;
K qdisp(I d)
{
K ignored = k(0, (S)"onCB", kj(54321), (K)0);
sd0(d);
return (K)0;
}
void* loop(void* vargs)
{
while(1) {
sleep(1);
sd1(d, qdisp);
}
return NULL;
}
K init(K ignore)
{
d = eventfd(1, 0);
int err = pthread_create(&tid, NULL, &loop, NULL);
return (K)0;
}
And here's the q script that invokes it:
/ testlib.q
init:`testlib 2:(`init;1)
onCB:{ 0N!x }
init[`blah]
Any tips or comments appreciated.
For those interested, it looks like sd1 schedules a function to be invoked every time there is data available to be read on a file descriptor, and sd0 removes the scheduled function from invocation.
So the idea is to write a function that attempts to read from the FD; if successful, invoke your q function via k() and return the result, if 0 just return 0, and if error call sd0.
#define KXVER 3
#include "k.h"
#include <pthread.h>
#include <sys/eventfd.h>
#include <stdio.h>
I d;
pthread_t tid;
K qdisp(I d)
{
J v;
if (-1 != read(d, &v, sizeof(J)) ) {
return k(0, "onCB", ki(v), (K)0);
}
sd0(d);
return (K)0;
}
void* loop(void* vargs)
{
J j = 0;
sd1(d, qdisp);
while(j++) {
sleep(1);
write(d, &j, sizeof(J));
}
return NULL;
}
K init(K cb)
{
d = eventfd(1, 0);
int err = pthread_create(&tid, NULL, &loop, NULL);
return (K)0;
}
Are you sure the other side provides enough data? As I see from the documentation referenced by you, communication is done by using blocking pipes. This means that if there is not enough data, or the buffer is not flushed by the producer, you application should block and this is its intended behavior.
You could try to use sd0()/sd1() skipping the d parameter to verify that the observed behavior is caused by blocking pipe and not by something else.

FreeBSD kldload: can't load, No such file or directory

I am new to kernel and KLD programming. I am looking to modify the example file in FreeBSD for system call module. My question is, is it possible to fork or exec inside system call function? Like in the following example?
#include <sys/types.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/kernel.h>
#include <sys/systm.h>
/*
* The function for implementing the syscall.
*/
static int hello (struct thread *td, void *arg)
{
printf("Running...\n");
/******************************************************/
/*Something like this?*/
/******************************************************/
execl("/bin/pwd", "pwd", NULL);
return 0;
}
/*
* The `sysent' for the new syscall
*/
static struct sysent hello_sysent = {
0, /* sy_narg */
hello /* sy_call */
};
/*
* The offset in sysent where the syscall is allocated.
*/
static int offset = NO_SYSCALL;
/*
* The function called at load/unload.
*/
static int
load (struct module *module, int cmd, void *arg)
{
int error = 0;
switch (cmd) {
case MOD_LOAD :
uprintf ("syscall loaded at %d\n", offset);
break;
case MOD_UNLOAD :
uprintf ("syscall unloaded from %d\n", offset);
break;
default :
uprintf("There was some error!");
error = EINVAL;
break;
}
return error;
}
SYSCALL_MODULE(syscall, &offset, &hello_sysent, load, NULL);
There is no compilation error (syscall), but while loading it using kldload, it returns an error:
kldload: can't load ./syscall.ko: No such file or directory
Is there something I can read and know more about why is this happening and what can I do about it?
When kldload returns "No such file or directory", or some other weird error, first do "dmesg" and look for any errors at the bottom. In this case it's probably due to a missing symbol "execl". That's because execl is a userspace API (man 3 execl), and you're trying to use it in kernel.
What you're trying to do doesn't seem to be a good idea, but it's possible. Look at sys/kern/kern_exec.c:kern_execve().

Linux timerfd> calling a function every x seconds without blocking the code execution

Need to call a function every X (let's say 5) seconds and the below code does it.
But it is blocking the execution of code. As I want it to work like setitimer(), where I can (for example) call a function every 5 sec and do something else.
#include <sys/timerfd.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h> /* Definition of uint64_t */
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{
struct itimerspec new_value;
int max_exp, fd;
struct timespec now;
uint64_t exp, tot_exp;
ssize_t s;
if (clock_gettime(CLOCK_REALTIME, &now) == -1)
handle_error("clock_gettime");
/* Create a CLOCK_REALTIME absolute timer with initial
expiration and interval as specified in command line */
new_value.it_value.tv_sec = now.tv_sec + 1;
new_value.it_value.tv_nsec = now.tv_nsec;
new_value.it_interval.tv_sec = 5;
new_value.it_interval.tv_nsec = 0;
max_exp = 5; //say 5 times
fd = timerfd_create(CLOCK_REALTIME, 0);
if (fd == -1)
handle_error("timerfd_create");
if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
handle_error("timerfd_settime");
printf("timer started\n");
for (tot_exp = 0; tot_exp < max_exp;) {
s = read(fd, &exp, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("read");
tot_exp += exp;
printf("read: %llu; total=%llu\n",
(unsigned long long) exp,
(unsigned long long) tot_exp);
}
//Do something else ?
//while(1);
exit(EXIT_SUCCESS);
}
EDIT
I have one more question.
On changing these lines in above code from
new_value.it_interval.tv_sec = 5;
new_value.it_interval.tv_nsec = 0;
to
new_value.it_interval.tv_sec = 0;
new_value.it_interval.tv_nsec = 5000000000;
I see that there is no 5 seconds delay. Whats happening here?
You need to understand how to use multiplexing syscalls like poll(2) (or the older select(2) which tends to become obsolete) and use them to test the readability of the file descriptor obtained by timerfd_create(2) before read(2)-ing it.
However, be aware that timerfd_create works only when that read call succeeded. So only when the poll says you that the fd is not readable can you do something else. That something else should be quick (last less than 5 seconds).
You might want to investigate event loop libraries, like e.g. libevent (wrapping poll). If you are coding a graphical application (using Qt or Gtk) it does already have its own event loop. If clever enough, you could do your 5-second period without any timerfd_create, just thru your event loop (by carefully setting the timeout given to poll, etc.).
Addenda:
the tv_nsec field should always be non-negative and less than 1000000000 (the number of nanoseconds in a second).
Any reason you have to use timerfd? Just schedule an alarm and make a handler for SIGALRM to call your function.
If you don't want to use signals, just create an extra thread to block on your timer fd and proceed as normal in the main thread.
If you don't like either of those and you want to do work while you're waiting, you have to poll. You can do it as basile suggests, or you could just store the current time and check whenever you would poll to see if the desired period has elapsed.

Resources