When opening the file /dev/urandom in nonblocking mode it is still blocking when reading. Why is the read call still blocking.
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int fd = open("/dev/urandom", O_NONBLOCK);
if (fd == -1) {
printf("Unable to open file\n");
return 1;
}
int flags = fcntl(fd, F_GETFL);
if (flags & O_NONBLOCK) {
printf("non block is set\n");
}
int ret;
char* buf = (char*)malloc(10000000);
ret = read(fd, buf, 10000000);
if (ret == -1) {
printf("Error reading: %s\n", strerror(errno));
} else {
printf("bytes read: %d\n", ret);
}
return 0;
}
The output looks like this:
gcc nonblock.c -o nonblock
./nonblock
non block is set
bytes read: 10000000
Opening any (device) file in nonblocking mode does not mean you never need to wait for it.
O_NONBLOCK just says return EAGAIN if there is no data available.
Obviously, the urandom driver always considers to have data available, but isn't necessarily fast to deliver it.
/dev/urandom is non-blocking by design:
When read, the /dev/random device will only return random bytes
within the estimated number of bits of noise in the entropy pool.
/dev/random should be suitable for uses that need very high quality
randomness such as one-time pad or key generation. When the entropy
pool is empty, reads from /dev/random will block until additional
environmental noise is gathered.
A read from the /dev/urandom device will not block waiting for more
entropy. As a result, if there is not sufficient entropy in the
entropy pool, the returned values are theoretically vulnerable to a
cryptographic attack on the algorithms used by the driver.
If you replace it with /dev/random, your program should produce a different result.
In Linux, it is not possible to open regular files in non blocking mode. You have to use the AIO interface to read from /dev/urandom in non blocking mode.
Related
I am trying accessing /dev/mem from user space. Using qemu-system-arm for this purpose.
UART0 is mapped: 0x101f1000 and UARTDR is placed at offset 0x0
$ devmem 0x101f1000 8 0x61
The above writes 'a' on the console.
When i try the achieve the same logic from C code, it fails
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd;
char ch = 'a';
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0) {
perror("open failed");
return -1;
}
if (lseek(fd, 0x101f1000, SEEK_SET) == -1) {
perror("lseek");
}
if (write(fd, &ch, sizeof(ch)) == -1) {
perror("write");
}
close(fd);
return 0;
}
It fails with error:
write: Bad address
Trying to access device registers by using the read and write syscalls on /dev/mem is not a good idea. /dev/mem implements those syscalls mostly for convenience in accessing RAM, and there is no guarantee about whether it will make accesses of the right width for the device if you try to do that on an area of the address space with a device there. For accessing devices you should instead use mmap() and then access the right addresses directly (which gives you more control about the width of the access and exactly which addresses are touched). For an example of this you can look at the source code for devmem itself: https://github.com/hackndev/tools/blob/master/devmem2.c -- at less than 100 lines of code it's very simple and you already know it works correctly for your use case.
[probably not your main problem but still]
lseek: Success
write: Bad address
You only want to use errno (or call perror()) is the previous call failed (and is documented to set errno on failure).
So this
lseek(fd, 0x101f1000, SEEK_SET);
perror("lseek");
should look like
if ((off_t) -1 == lseek(fd, 0x101f1000, SEEK_SET))
{
perror("lseek() failed");
}
Same for the call to write(), BTW.
I want to remote control sockets in my room manual without an extra library on my raspberry pi. I want to use the UART interface in C. The socket has 433 Mhz receiver and I use a 433 Mhz transmitter. In other librarys you type something like this: send 11111 1 1. (socket code, socket number, condition). But how to format this command in C with the write() function? The 10 is for number of characters. I use this code below. I tested the output via minicom, that works fine. But how the receiver now knows that it was adressed?
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
int main(int argc, char ** argv) {
int fd;
// Open the Port. We want read/write, no "controlling tty" status, and open i$
fd = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("open_port: Unable to open /dev/ttyAMA0 - ");
return(-1);
}
// Turn off blocking for reads, use (fd, F_SETFL, FNDELAY) if you want that
fcntl(fd, F_SETFL, 0);
// Write to the port
int n = write(fd,"11111 1 1",10);
if (n < 0) {
perror("Write failed - ");
return -1;
}
// Don't forget to clean up
close(fd);
return 0;
}
Do I get it right: you send a command via UART to transmit a message via radio trasmitter. Sniffing the UART output proves your code OK in the sense that TX line sends what you want it to send in the software, and the actual question is "how the rx module gets that message/how to make the rx module get it?"
If so, the main question is what kind of radio TX/RX or TRXs do you actually use (I mean chip/module codes, like CC1120, NRF2401 etc.)? There are plenty of 433MHz radiomodules available, I suppose consulting their datasheet first or at least posting the part number here is the right way to go.
I modified a program from APUE, the program first open a file, then mark the fd as non-blocking, then continue write to the fd until write return -1.
I think since disk I/O is slow, when write buffers in OS is nearly full, the write system call will return -1, and the errno should be EAGAIN or EWOULDBLOCK.
But I ran the program for about several minutes and I repeated running the program serveral times, the write system call didn't returned -1 even once! Why?
Here's the code:
#include "apue.h"
#include <errno.h>
#include <fcntl.h>
char buf[4096];
int
main(void)
{
int nwrite;
int fd = open("a.txt", O_RDWR);
if(fd<0){
printf("fd<0\n");
return 0;
}
int i;
for(i = 0; i<sizeof(buf); i++)
buf[i] = i*2;
set_fl(fd, O_NONBLOCK); /* set nonblocking */
while (1) {
nwrite = write(fd, buf, sizeof(buf));
if (nwrite < 0) {
printf("write returned:%d, errno=%d\n", nwrite, errno);
return 0;
}
}
clr_fl(STDOUT_FILENO, O_NONBLOCK); /* clear nonblocking */
exit(0);
}
The O_NONBLOCK flag is primarily meaningful for file descriptors representing streams (e.g, pipes, sockets, and character devices), where it prevents read and write operations from blocking when there is no data waiting to read, or buffers are too full to write anything more at the moment. It has no effect on file descriptors opened to regular files; disk I/O delays are essentially ignored by the system.
If you want to do asynchronous I/O to files, you may want to take a look at the POSIX AIO interface. Be warned that it's rather hairy and infrequently used, though.
I have an issue that I'm trying to solve regarding the serial port in Linux. I'm able to open, read from, and close the port just fine. However, I want to ensure that I am the only person reading/writing from the port at any given time.
I thought that this was already done for me after I make the open() function call. However, I am able to call open() multiple times on the same port in my program. I can also have two threads which are both reading from the same port simultaneously.
I tried fixing this issue with flock() and I still had the same problem. Is it because both systems calls are coming from the same pid, even though there are different file descriptors involved with each set of opens and reads? For the record, both open() calls do return a valid file descriptor.
As a result, I'm wondering if there's any way that I can remedy by problem. From my program's perspective, it's not a big deal if two calls to open() are successful on the same port since the programmer should be aware of the hilarity that they are causing. However, I just want to be sure that when I open a port, that I am the only process with access to it.
Thanks for the help.
In Linux, you can use the TIOCEXCL TTY ioctl to stop other open()s to the device from succeeding (they'll return -1 with errno==EBUSY, device or resource busy). This only works for terminals and serial devices, but it does not rely on advisory locking.
For example:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <fcntl.h>
#include <errno.h>
int open_device(const char *const device)
{
int descriptor, result;
if (!device || !*device) {
errno = EINVAL;
return -1;
}
do {
descriptor = open(device, O_RDWR | O_NOCTTY);
} while (descriptor == -1 && errno == EINTR);
if (descriptor == -1)
return -1;
if (ioctl(descriptor, TIOCEXCL)) {
const int saved_errno = errno;
do {
result = close(descriptor);
} while (result == -1 && errno == EINTR);
errno = saved_errno;
return -1;
}
return descriptor;
}
Hope this helps.
I was able to fix the issue with use of the flock() function. Use of the structure and fcntl() wasn't working for me for some reason. With use of flock() I was able to add two lines of code and solve my issue.
I am new to serial programming in Linux using C. I have found a small piece of code to write data on serial port which I am sharing here. After running this code I may assume that data has written on a specific port. Now I would like to open another terminal and using separate code want to read the data written on that specific port - how do I do that?
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
/*
* 'open_port()' - Open serial port 1.
*
* Returns the file descriptor on success or -1 on error.
*/
int
open_port(void)
{
int fd; /* File descriptor for the port */
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
/* Could not open the port. */
perror("open_port: Unable to open /dev/ttyS0 - ");
}
else
fcntl(fd, F_SETFL, 0);
n = write(fd, "ATZ\r", 4);
if (n < 0)
fputs("write() of 4 bytes failed!\n", stderr);
return (fd);
}
The code above will write the data on a specific port.
In theory, all you have to do is open the relevant port for reading, and use read() to get the data.
int
read_port(void)
{
int fd = open("/dev/ttyS0", O_RDONLY | O_NOCTTY);
if (fd == -1)
{
/* Could not open the port. */
perror("open_port: Unable to open /dev/ttyS0 - ");
}
char buffer[32];
int n = read(fd, buffer, sizeof(buffer));
if (n < 0)
fputs("read failed!\n", stderr);
return (fd);
}
There are differences; notably, the read needs a buffer to put the data in. The code shown discards the first message read. Note that a short read simply indicates that there was less data available than requested at the time when the read completed. It does not automatically indicate an error. Think of a command line; some commands might be one or two characters (ls) where others might be quite complex (find /some/where -name '*.pdf' -mtime -3 -print). The fact that the same buffer is used to read both isn't a problem; one read gives 3 characters (newline is included), the other 47 or so.
The program posted makes a lot of assumptions about the state of the port. In a real world application you should do all the important setup explicitly. I think the best source for learning serial port programming under POSIX is the
Serial Programming Guide for POSIX Operating Systems
I'm mirroring it here: https://www.cmrr.umn.edu/~strupp/serial.html