Read/Write system call reads/writes data from/to which buffer - c

I am working with serial port programming and i have following doubt please clear it
Does Read/Write system call reads and writes data directly from/to UART buffer?
Which buffer does Rx and Tx of "/proc/tty/driver/serial" refers to.
Please clarify.

read()and write() access data via a so called file-descriptor return by a call to open().
open() gets passed in the name of a serial device.
Serial devices could be named "/dev/ttySX" with X={0..N}.

Why are you worried about:
Does Read/Write system call reads and writes data directly from/to
UART buffer?
The kernel takes care of the actual read/write calls to a file regardless if its a device or a data file, in the case of device, IOCTL calls will be made to the device in question and handle it behind the scenes.
Which buffer does Rx and Tx of "/proc/tty/driver/serial" refers to.
Again, that is handled by the kernel and related IOCTL calls to the serial driver by way of device descriptor to the actual serial port.
If still in doubt, a refresher on serial port programming under Un*x environments such as Linux/FreeBSD would be recommended.

Related

Can an ethernet buffer fill up and not allow another process to recv() ethernet packets?

Say you have a process that receives a large file from a server.
If you do not perform a recv() call does it stay on a buffer of your ethernet controller forever?
If another process needs to receive data and the buffer is full from another process does it need to wait until the other process performs a recv() or the buffer times out?
If you have multiple process sending and receiving data does it have to wait until the buffer is empty.? Or can it multiplex it and keep track at the driver level or some part of the socket library?
edit: spelling
If you do not perform a recv() call does it stay on a buffer of your
ethernet controller forever?
No, data never stays in the ethernet controller's buffer for very long; the kernel will read the data out of the Ethernet controller's buffer and into your socket's buffer (in the computer's regular RAM) as quickly as it can. If your socket's buffer is full, then the incoming data will be discarded.
If another process needs to receive data and the buffer is full from
another process does it need to wait until the other process performs
a recv() or the buffer times out?
Each socket has its own separate buffer in the computer's main RAM, and each process has its own socket(s), so processes do not have to wait for each others' buffers to empty.
If you have multiple process sending and receiving data does it have
to wait until the buffer is empty.?
See the answer to question 2, as it answers this question also.
This is a bit of perfectly spherical chicken in a vacuum type of answer. But your question is very broad and has a lot of what ifs depending on the NIC, the OS, and many other things.
But lets assume your are on a modernish full-blown OS, with modernish ethernet controller.
No. That all handled by the by kernel and protocol stuff. The kernel can't let the buffer on the network controller fill up while it's waiting for you. Otherwise it will block other processes from accessing the network. So it will buffer it up until you are ready. For some protocols there are mechanism where one device can tell the other device not to send any more data. (ei. TCP Receive Window Size, once the sender sent that amount of data it will stop until the receiver acknowledges it somehow)
It's basically the same answer as above, the OS handles the details. From your point of you, your recv() will not block any other processes ability to recv().
This is more interesting, modern NIC are queue based. You have n-number of transmit/receive queues, and in most cases, filters can be attached to them. This allows the NIC to do a lot of the functionality that normally would have to be done by the OS (that's called offloading) but back to the point. With these NICs, you have have multiple I/O without multiplexing. Though generally, especially on consumer grade NIC, the number of queues will be pretty low. Usually 4. So there will be some multiplexing involved.

BeagleBone Black UART software FIFO size?

I'm developing a custom application on the BeagleBone Black that has to use the UART capabilities of the device via the Debian Linux that runs on the BBB, for reading big chunks of data. For reading from the UART I'm opening one of the /dev/ttyO0, /dev/ttyO1, etc. devices with the open() function in nonblocking mode. And then I'm trying to read from this port with the read(2) function:
ssize_t read(int fd, void *buf, size_t count);
I would like to know what is the biggest reasonable number for the parameter count and how is it related to the UART's FIFO buffer?
In the AM335x technical reference manual (TI document spruh73p, page 4328, section 19.3.6) I can see that the HW buffer is 64 bytes long. But, as I suspect by using the read() function my program is not communicating directly with the hardware fifo buffer but it is reading from Linux' serial driver's software buffer (if there is such). Is this true? If yes, what is the size of the software fifo? Could somebody please enlighten this field for me?
And then I'm trying to read from this port with the read(2) function
Rather than the "port", you are actually several layers removed from the hardware device, and reading from the system buffer of the serial terminal.
I would like to know what is the biggest reasonable number for the parameter count and how is it related to the UART's FIFO buffer?
First of all the count must be no larger than the user buffer provided.
For a blocking read(), you could probably make this count as large as any buffer you could allocate.
For a nonblocking read(), a count larger than the terminal receive buffer makes little sense.
Note that count is merely a request, and the read() syscall can return with less than the requested number of bytes.
The sizes of the UART FIFO and serial port driver buffers are irrelevant to any read() requests from userspace.
See Linux serial drivers.
... it is reading from Linux' serial driver's software buffer (if there is such). Is this true?
Almost.
The read() syscall from userspace fetches data from the terminal buffer.
The terminal driver is a higher-level driver than the serial port driver.
The terminal buffer has no direct connection to the UART FIFO.
If DMA is employed, then data is transferred from the UART FIFO to a DMA buffer.
If PIO is employed, then data is transferred from the UART FIFO to a driver buffer.
In either case the serial port driver eventually transfers the data to a tty flip buffer.
In non-interrupt mode, data from the tty flip buffer is transferred to the terminal/line-discipline buffer.
Again refer to Linux serial drivers.
If yes, what is the size of the software fifo?
The terminal receive buffer is typically 4096 bytes, although you could write your own line discipline with a different size, or redefine the macro.
From include/linux/tty.h in Linux kernel source:
#define N_TTY_BUF_SIZE 4096
The terminal driver is common to all architectures supported by Linux, so your BBB should have a terminal buffer of 4096 bytes.

how to access the kernel memory from user program in rt linux?

client and server communication in rt linux. client is sending the data and server is the receiver.UDP is used for communication between client and the server.
When the server(rt linux) receives the data from the client the kernel should stop what it is doing and start executing the newly arrived data. I want to calculate the time when the interrupt occurs in kernel (timestamp).
In rt-linux all the operating system operation takes place in kernel. So i am calculating the interrupt time in kernel source code. So i modified the kernel source code in the location /usr/src/linux-version/net/core/dev.c as shown below :
I am calculating the time and storing in a buffer skb.
//this code is at network device driver level.
int netif_rx(struct sk_buff *skb)
{
__net_timestamp(skb);//I modify the code in kernel to get the timestamp and store in buffer
}
// after storing the data to the buffer. kernel will send it to the upper layers like IP, UDP, INET and finally SOCKET of the kernel space.
but I want to read the timestamp packet from the kernel space by the user space. i.e. my program .
I am using recvfrom api to read the data from kernel spacce (which is in kernel memory)
QUESTION : could someone tell me how to access the kernel memory which contains the timestamp data by the user program ??
You can't access kernel memory from userspace directly - you have to use some sort of API.
You can:
Export timestamp through sysfs or debugfs and read it as regular file
Add syscall so kernel will return current timestamp value
Bunch of other crazy variants like netlink socket or shared memory

read() and write() using spi device driver

I would use the read() and write() for the /dev/spiB.C which is created by the user mode spi device driver (spidev.c). Now, the SPI ransaction message follows a certain format (e.g., 24 bits, with some bits for address and some bits for data) which is defined by the chip-vendor-specific spi controller driver. How is the message format fit into the read() and write() transaction? Where and how should I define the format in the code before or after the write() or read()?
Thanks!
You need to call spidev_ioctl() mentioned in spidev.c
E.g. Just check switch case :SPI_IOC_RD_BITS_PER_WORD which sets the bits/word (line 410).
Then finally it writes to the bits_per_word member in the spi device structure (line 415).
This spi pointer is the pointer of the spi device which you are communicating to and has been allocated during spidev_probe().
Definitely you need to set the configuration before r/w.You also need to set speed and mode of SPI.
I have refered to the below link for spidev.c file:
http://lxr.free-electrons.com/source/drivers/spi/spidev.c

Linux C Programming: Concurrent reads/writes to same file descriptor

I am writing a program that interfaces with a particular serial device. The serial device has two channels, and a hardware rx and tx buffer for each channel. Basically, at any given time , you can read/write to either channel on the device.
I am trying to read data from a channel, validate it (and perhaps use some of the data), and then transmit it. Reads are accomplished with iotctl calls to the device, while writes are accomplished with a call to the write() system call.
The main issue I have is with data throughput. I'd like to have an individual thread handle reading and writing for each channel (i.e., a read thread and write thread for each of the two channels). However, I have hit a snag. Everything on the device, from Linux's perspective is accessed via one single device, and I'm not sure that Linux notes that the device has multiple channels.
As a result, currently I open a single file descriptor to the device and perform my reads and writes serially. I'd like to go to the threaded approach, but I'm wondering if concurrent ioctl() and write() calls would cause issues. I understand that read() and write() and not thread safe, but I was wondering if there's any way around that (perhaps calling open() twice, one with read privileges, one with write privileges).
Thanks for your help. Also, I want to avoid having to write my own driver, but that may be an inevitable conclusion...
Also, as a side note, I'm particularly concerned that the device has extremely small hardware buffers. Is there any way to determine how much space the OS uses for a software buffer for data? That is, can I determine whether or not the OS has it's own buffer that is used to prevent overflow of the hardware buffer? The device in question is an I2C UART Bridge.
You can use semaphore to make a mutual exclusion between read/write thread
sem_t sync_rw;
/*init semaphore */
err=sem_init(&sync_rw,0,1); /* shared between thread and initialized with 1 */
if( err != 0 )
{
perror("cannot init semaphore \n");
return -1;
}
in thread write function you do this :
sem_wait(&sync_rw);
write(...)
sem_post(&sync_rw);
same for thread reader :
sem_wait(&sync_rw);
iotctl(...)
sem_post(&sync_rw);
finally :
sem_destroy(&sync_rw);

Resources