How to implement a timer callback function in C under Linux

I searched for a possible solution in many forums for several days, but I was out of luck; (I am posting my question here, and your answer is greatly appreciated.

IDEA: Use a script to control lights (in C under Linux)

SCENARIO OF APPLICATION I have three lights: red, blue and green. The script has graphs for managing them. For example, After 10 seconds, turn on the red light for 2 seconds; From now on, after 15 seconds turn on the blue light for 10 seconds; From now on, after 21 seconds turn on the red light for 5 seconds; After 5 seconds, turn on the green light for 7 seconds; From now on, after 103 seconds, turn on the green light for 11 seconds; ..... When and for how long to turn on the light, they are absolutely arbitrary. And this program should be able to expand to hundreds of light and thousands of schedules.

HOW TO COD THIS My idea is to have two processes and one mailbox: The first process reads the script file and analyzes the graphs in many timers. After the timer expires, it sends a message (including the light identifier and the action is ON or OFF) to the mailbox. The second process is to turn on or off the specified light based on the message from the mailbox.

Each schedule will be analyzed for two timers: Schedule: now after 10 seconds turn on the red light for 2 seconds; Designed for: Timer 1: The timer expires in 10 seconds; after the expiration, it sends the light identifier (red light) and the action (ON) as a message to the mailbox; Timer 2: the timer expires in (10 + 2) seconds; after the expiration of the term, it passes the light identifier (red light) and the action (OFF) as a message in the mailbox;

The second process constantly checks the mailbox and takes the right action with the right lighting based on the message received.

MY QUESTION The timer on Linux () only emits the same expired SIGALRM signal. Unable to transfer the identifier and the action of the light to the mailbox. Do I have another way to do this? Thank you very much.

+4
source share
2 answers

SIGALRM is not a very reliable way to implement something like this; you cannot have more than one alarm request at a time. And was it that the two processes were intended as in (1) / atd (8)? Unfortunately, "at" is not so accurate that it can be used here, I'm not sure if it even takes seconds when you are planning something.

However, the problem is very simple to solve with just one program. Just divide the task into events such as β€œturn on / off the light X”, put them in an ordered queue and have a loop that reads the queue and sleeps until the time comes.

+3
source

Tonttu's solution is pretty good.

Use the queue implemented with the linked list:

struct node { struct node *next; time_t t; // time to start int action; // on / off int lamp_id; }; struct queue { struct node *head; struct node *tail; }; 

Parse your file and fill out the queue (keep it sorted by t). Then your main loop should look like this:

 time_t start = time(NULL); while(!queue_empty()) { time_t now = time(NULL) - start; struct node *n = queue.head; if(n->t <= now) { lamp(n->lamp_id, n->action); // set the status of a lamp queue_next(); } else { sleep(n->t - now); } } 

As usual, read the exact manual. You will need time (2) . If you need a sub-second time, use gettimeodday (2) .

+3
source

Source: https://habr.com/ru/post/1336147/


All Articles