C - infinite read from cat in Device file - c

I've been having some headache with infinite reads from cat (cat doesn’t close because it doesn’t receive end of function from my read function. How can I implement an end of read so that reading the file with cat will only produce 1 output per command in the terminal?
function. This is the kernel read() function I've written:
static ssize_t dev_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
char tmp_buf[MAX_BUF_SIZE]; //defined as 100
int bLen=0;
sprintf(tmp_buf, "Some message");
bLen = strlen(tmp_buf);
if(copy_to_user(buf,tmp_buf, bLen)){
return -EFAULT;
}
return bLen;
}

I'm answering because I found this early on in my search.
Cat continually reads until it gets an empty response. Once it finished getting some data it goes back and asks "have anything else?" To which your module says yes and sends it the data again. You need to break the chain and have it send an empty response. The best way to do this would be to place
if(*ppos > 0){
return 0;
}
at the beginning of the function and add the length of the data you are sending back to *ppos before exiting.

Related

Writing to Linux device driver causes infinite loop

I have been writing a kernel space device driver that can be read from and written to from user space. The open, read, release operations all work perfectly. The problem I am having is with the user-space code that should access the device driver and and write something to it.
The user-space program writes to two files: 1) to a .txt file (and prints a to the console to let the user know it was completed), and 2) to the device driver (and also prints a text to let the user know it was also completed).
Below is the user-space code in full:
int main() {
FILE *fp;
fp = fopen("./test.txt","w");
fputs("Test\n", fp);
fclose(fp);
printf("Printed to txt\n"); //Prints normally.
fp = fopen("/dev/testchar", "w");
fputs("Test\n", fp);
fclose(fp);
printf("Printed to dev\n"); //Never gets to this point
return 0;
}
When I compile and run the code the program spits out
Printed to txt
and just hangs until ctrl+c is called. It never gets beyond the second fputs().
While monitoring kern.log I see endless calls to write to the device driver.
Here I have extracted relevant code from the device driver:
static char msg[256] = {0};
static struct file_operations fops =
{
.write = dev_write
};
static ssize_t dev_write(struct file *file, const char *buf, size_t len, loff_t *ppos)
{
sprintf(msg, "Input:%s, Chars:%lu\n", buf, len);
printk(KERN_NOTICE "%s\n", msg);
return 0;
}
uname -r: 4.10.0-38-generic
gcc -v: gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
My question is: why is the program getting stuck in an infinite loop when writing to the device, and how do I fix it?
Thanks in advance. Any help will be greatly appreciated.
I think the kernel write operation is supposed to return the number of bytes written. You return 0. So the write system call returns to userspace with 0. However, since your userspace code is using stdio, then your userspace code tries the write again, assuming the system call simply didn't write out all the data. If you return the length of the input, then stdio will know all the data was written. Alternatively you can use the write system call directly rather than fputs. Your kernel code will still be incorrect, but your program will terminate.
You can test this using strace and see all the system calls.

How can i save all output to the screen while still displaying it?

I am currently writing a custom shell for a CS course.
It is a basic shell that reads in user input, and checks for shell functions, and then forks itself and passes the commands that were parsed to execvp().
I need to save the output from the screen into a text file while the shell is currently being run. I looked into freopen but that cut off all printing to the screen.
Can anyone give me a hint in which direction to look to perform this functionality?
You need something which will read from standard input and write same thing into both standard output as well standard error, that way you can print one, while save other in file.
Here is a simple implementation:
#include <stdio.h>
#include <unistd.h>
#define BUF_SIZE 1000
int main ()
{
char buffer[BUF_SIZE];
ssize_t read_size;
while ((read_size = read (STDIN_FILENO, buffer, BUF_SIZE)) > 0)
{
if (write (STDOUT_FILENO, buffer, read_size) <= 0 ||
write (STDERR_FILENO, buffer, read_size) <= 0)
return 1;
}
return 0;
}
If program is called dupl then you can do something like this
ls | ./dupl 2> file
This will display and as well save standard output of ls into file

where will be the output of the user from kernel using procfs?

ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *offset)
{
int len = count >= strlen(chr_arr.array) ? strlen(chr_arr.array) : count;
*offset += len;
if (*offset >= strlen(chr_arr.array))
return 0;
if (copy_to_user(buf,chr_arr.array,len))
return -EFAULT;
return len;
}
I want to read a value from kernel and use it in a user application, so i am using procfs api to read from the kernel and use it in a user space.
The above is the read function to read from the kernel and store it in a user buffer(buf). But If i want to read the output from user application then where will be value read from kernel stored in a user space ?? could someone help me in this ??
If the value is exposed in procfs, your user application just needs to open the procfs node as a file and read it like any other file. The fancy stuff's all done in the kernel.
If you're trying to write a kernel component that exposes something to procfs, then you'll need something similar to the code that you quoted to handle read() calls to the procfs node.

Printing to a file while conducting n simulations for a program (in C)

I am conducting n simulations using a program and albeit everything being correct, there is only one mistake which I am able to see in the output files.
I am printing the outputs of the program to a csv file.
I check the file before I print to it to get it's size which if it is 0, I print the headers. Here is the function which does the same:
void Data_Output(FILE *fp, int node_num, int agg_num, int cnode, int sysdelay, int bwdth_reqt)
{
struct stat buf;
int fd = fileno(fp);
fstat(fd, &buf);
//Debug Statement
fprintf(stderr,"%d-",buf.st_size);
if (!buf.st_size) {
// Writing Headers
fprintf(fp,"Tot_Nodes_Num,Agg_Nodes_Num,Central_Node_Num,Tot_System_Delay,Bandwidth_Reqt\n");
}
// Writing Data
fprintf(fp,"%d,%d,%d,%d,%d\n",node_num,agg_num,cnode,sysdelay,bwdth_reqt);
}
For 100 simulations, the output I get from the debug shows me:
0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-
What am I doing wrong? I suspect that the program stores everything in a buffer and only prints everything to the file after it is done with the simulations and the files are closed.
Note: I open and close the files only once during the whole program and not for each simulation.
You are correct. Stdio has it's own output buffering and fstat is only concerned with logical files. So the file writes do get delayed. Try putting fflush(fp); for the last line in your Data_Output function. I hope that helps.

I/O issues writing on file

I'm having a hard time trying to figure out why this piece of code doesn't work as it should. I am learning the basics of I/O operations and I have to come up with a C program that writes on a 'log.txt' file what is given from standard input and as the 'stop' word is entered, the program must halt.
So my code is:
#include "main.h"
#define SIZE 1024
int main(int argc, char *argv[])
{
int fd;
int readBytes;
int writBytes;
char *buffer;
if ((fd = open("log.txt", O_WRONLY|O_APPEND)) < 0)
{
perror("open");
}
buffer = (char *) calloc (SIZE, sizeof(char));
while ((readBytes = read(0, buffer, SIZE) < SIZE)&&(strncmp(buffer, "stop", 4) != 0));
if ((writBytes = write(fd, buffer, SIZE)) < 0)
{
perror("write");
}
if ((close(fd)) < 0)
{
perror("close");
}
}
If I enter:
this is just a text
stop
The output is
stop
is just a text
If I enter more than a sentence:
this is just a text
this is more text
and text again
stop
This is what is logged:
stop
ext again
xt
t
And on top of that if I try to edit the log.txt file from vim or just a text editor I can see '\00's. I guess \00 stands for all the bytes left empty from the 1024 available, right? How can I prevent that from happening?
It looks like you're expecting
readBytes = read(0, buffer, SIZE) < SIZE)
to somehow accumulate things in buffer. It doesn't. Every subsequent read will put whatever it read at the start of the buffer, overwriting what the previous read has read.
You need to put your write in the while block - one write for every read, and only write as much as you read, otherwise you'll write garbage (zeros from the calloc and/or leftovers from the previous read) in your log file.
Also note that while your technique will probably work most of the time for a line-buffered input stream, it will not do what you expect if you redirect from a file or a pipe. You should be using formatted input functions (like getline if you your implementation has that, scanf, or fgets).

Resources