Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Four Approaches for Applications to Access Hardware Resources

Tech 1

Polling Method

In polling mode, applications continuously check whether data is available.

  • When calling the open function, passing O_NONBLOCK sets non-blocking mode.
  • During a read call, if data exists in the driver, it returns immediately with the data; otherwise, it returns an error right away.
int device_fd = open(argv[1], O_RDWR | O_NONBLOCK);

Blocking Sleep-Wakeup Mechanism

With this approach, the application waits until the driver provides data.

  • The open function is called without O_NONBLOCK.
  • If data is present during a read, it returns immediately. Otherwise, the process sleeps in kernel space and resumes execution once the driver signals availability of data.
int device_fd = open(argv[1], O_RDWR);

Event Monitoring with poll/select

These functions allow specifying timeout periods. They return either when conditions are met or upon expiration of the timeout.

  • First, use open to obtain a file descriptor.
  • Instead of calling read directly, invoke poll or select with a defined timeout.
  • Based on their return status, proceed to call read which will then fetch data instantly.
  • Both poll and select support monitoring multiple file descriptors and various types of events.

To configure polling:

  • Specify the target file descriptor.
  • Define the event type (POLLIN for read readiness, POLLOUT for write readiness).
#include <poll.h>

struct pollfd monitor_list[1];
int device_fd = open(argv[1], O_RDWR | O_NONBLOCK);

monitor_list[0].fd = device_fd;
monitor_list[0].events = POLLIN;
monitor_list[0].revents = 0;

int result = poll(monitor_list, 1, 5000); // Wait up to 5 seconds

Asynchronous Notification

Asynchronous notification allows the application to perform other tasks while receiving automatic alerts from drivers when data becomes available.

Key aspects of signal delivery:

  • Signal Source: Device driver
  • Signal Type: Typically SIGIO
  • Delivery Mechanism: Kernel-provided signaling APIs
  • Recipient: Application process (must register itself)
  • Response Action: Execution of a custom signal handler
  • Handler Registration: Associating the handler with the specific signal

Implementation steps:

void handle_signal(int sig_num)
{
    struct input_event evt;
    while (read(device_fd, &evt, sizeof(evt)) == sizeof(evt))
    {
        printf("Event received: type=0x%x, code=0x%x, value=0x%x\n", 
               evt.type, evt.code, evt.value);
    }
}

/* Register signal handler */
signal(SIGIO, handle_signal);

/* Open device in non-blocking mode */
device_fd = open(argv[1], O_RDWR | O_NONBLOCK);

/* Inform driver about application's PID */
fcntl(device_fd, F_SETOWN, getpid());

/* Enable asynchronous notifications */
int current_flags = fcntl(device_fd, F_GETFL);
fcntl(device_fd, F_SETFL, current_flags | FASYNC);

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.