Locking UART for atomic access to ressource

Hello,

I’m working with embedded linux (kernel 4.19).
I am working on dynamic UART changing mode rs485/rs232 with a tranceiver that permit the both possibility of transmissions. Actually, I do that changing mode with a c script using ioctl to drive CTS,RTS signals. It works fine, but to “securize” the process, I would like to enable the changing mode only if UART is not already use by an other script.

For exemple, let’s take uart0: “/dev/ttyuart0” that have got RTS and CTS.

so, when i want to transmit data, I use a c script with serial librarie and the data is transmitted during 2 minutes. During this time, I change successively the mode of data transmission (rs485<->rs232). The change of mode works fine (I verified signals with my oscilloscope), but data seems to don’t be transferred all the time. So I would like something to “lock” the uart if a process using it (when the file is open to push data), and release it after data transmission or close of “/dev/ttyuart0”.

I have already tested many things: monitoring by using linux “inotify”. The monitoring works fine and I succes to catch the events when a serial console like minicom open “/dev/ttyuart0” for example. But, the second part tat consist to lock the uart is a bit difficult. I try to use lockf function, but it does not work.

If you get any idea to do something like that, or a best idea, I’ll take it to investigate.

Thanks by advance, best reguards.

What do you mean by “does not work”? By default file locks in Unix systems are advisory (meaning both scripts need to make lock calls before accessing a file).

Hello danielt,
Thanks for the reply
I mean I’m not able to understand how " lockf c function " works. I read many documentations and test many c programs using it, but the behavior is not what i was thinking about.

In my head, after reading documentation in the website http://manpagesfr.free.fr/man/man3/lockf.3.html, and this site: https://www.editions-eni.fr/open/mediabook.aspx?idR=85a96ece19e334d9c274518d81a49e08,

I thought it was enough to just set a lock with F_TLOCK or F_LOCK mode with a c program (for example Lockfile.c), and then use F_TEST mode in an other program in c (isLock.c) would just have to check for that lock, but that sounds more complicated than that.

I tried this code to lock a file:


---------------- Lockfile.c ------------------

#include <stdlib.h> /* for exit() /
#include <stdio.h> /
for perror() /
#include <unistd.h> /
for lockf(), lseek() /
#include <fcntl.h> /
for open() */

int main(int argc, char *argv) {
/
open file: we need O_RDWR for lockf */
int fd = open("/dev/ttyuart0", O_RDWR);
if (fd == -1) {
perror(“open”);
exit(EXIT_FAILURE);
}
if (lockf(fd, F_LOCK, 0) == -1) {
perror(“lockf(LOCK)”);
exit(EXIT_FAILURE);
}else{
printf(“file /dev/ttyuart0 locked\n”);
}
}

and this code to verify that the file is locked:


---------------- isLocked.c -------------------

#include <stdlib.h> /* for exit() /
#include <stdio.h> /
for perror() /
#include <unistd.h> /
for lockf(), lseek() /
#include <fcntl.h> /
for open() */

int main (int argc , char *argv[]) {
int fd;
fd = open("/dev/ttyuart0", O_RDWR);
if(lockf (fd, F_TEST, 0) < 0){
printf (“File /dev/ttyuart0 is locked\n”);
}else{
printf(“File /dev/ttyuart0 is unlocked\n”);
}
close(fd);
}

The cross compile for my board is ok without error or warnings.

When I use the script Lockfile, I have the message “file /dev/ttyuart0 locked”, that is the expected, behaviour, but after that, when I execute the isLocked script, I have the message: “File /dev/ttyuart0 is unlocked”. That’s weird because I lock it with the first script before. Furthermore, when I execute twice the script Lockfile, the second time, I have the response: “file /dev/ttyuart0 locked”, that’s weird because as it is already lock, I expected it to return an error but that not the case.

Both scripts are following executed. Maybe to solve my problem I need something other than lockf statement, but I don’t know what.

Here is an exemple of execution:


root@pc:~# ./ Lockfile
file /dev/ttyuart0 locked
root@pc:~# ./ isLocked
File /dev/ttyuart0 is unlocked
root@pc:~# ./ Lockfile
file /dev/ttyuart0 locked
root@pc:~# ./ Lockfile
file /dev/ttyuart0 locked
root@pc:~# ./ isLocked
File /dev/ttyuart0 is unlocked

If you have an idea about what’s I’m doing wrong or conceived wrong about the behaviour of lockf, thanks in advance. Have you got an idea about how to really lock and test locking file with two different scripts.

best reguards.

The locking code looks OK but the Lockfile.c program doesn’t seem to do anything useful. It just exits… and when it exits the file handle is automatically closed and the lock is released.

Hello,

Thanks for the response. Have you got an idea about how to simply modify the code of “Lockfile.c” to observe this behaviour:

root@pc:~# ./ Lockfile
file /dev/ttyuart0 locked
root@pc:~# ./ isLocked
File /dev/ttyuart0 is locked
root@pc:~# ./ Lockfile
file /dev/ttyuart0 is already locked, you have to unlock it
root@pc:~# ./ Lockfile
file /dev/ttyuart0 is already locked, you have to unlock it
root@pc:~# ./ isLocked
File /dev/ttyuart0 is locked


Thanks for your yesterday’s explanations. Best reguards.

Don’t exit the program that establishes the lock and the lock won’t be closed.
You need to move the lock code to the program that IS supposed to access the resource, and should maintain the lock only as long as that program needs to maintain access to it.

int main(){
  fd = open(...);
  if (lockf(fd, F_LOCK, 0) == 0){
    do_stuff_with_fd(...);
    lockfd(fd, F_ULOCK, 0);
    close(fd);
  }
}

While do_stuff_with_fd(…) is running, your “isLocked” program will print that its locked.