How to minimize the number of system calls read() and write() in my code ?
int copy(char* entry, char* exit){
char buf;
int in;
int out;
in = open(entry,O_RDONLY);
out = open(exit ,O_APPEND|O_WRONLY);
while(read(in, &buf, 1) != 0){
write(out, &buf, 1); }
close(in);
close(out);
return 0;
}
Assuming you enlarge your buffer to for example 256, now write:
char buf[256];
int n;
...
while((n=read(in, buf, sizeof(buf))) > 0){
write(out, buf, n);
}
This reads, upon every read, a maximum of 256 bytes. read returns the number of bytes read, so n now has this number, which is what you write out. The last read will be less than 256, so the last write will also be less than 256.
Related
I want to pass int to sysfs_store
What I tried
userspace
int tid = 5234; // can be negative as well
char buf[5];
sprintf(buf, "%d\n", tid);
write (fd, buf, 1);
driver sysfs_store
int v;
kstrtoint(buf,10,&v);
pr_info("%d\n",v); // printing only first digit 5. Should print 5234
Since sprintf() returns bytes copied count; use it
Also switch to snprintf() to avoid buffer overflows.
int data_len = snprintf(buf, sizeof(buf), "%d\n", tid);
write (fd, buf, data_len);
It's always better to have bigger buffers to cover all your scenarios.
I have to create a program that asks from standard input a string and write in standard error the string previously written.
This is my program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main() {
char *buffer = malloc(sizeof(char)*20);
int len = 0;
do {
len = read(STDIN_FILENO, buffer, 20);
if(len == -1)
write(STDERR_FILENO, "Error read\n", 10);
else
write(STDERR_FILENO, buffer, len);
} while(strncmp(buffer,"fine\n", 5));
free(buffer);
return 0;
}
The code works but I'm not satisfied..there is one problem:
The buffer is a 20char but I can insert more than 20 char...why? How I can limit the buffer to only 20 char?
The code works but I'm not satisfied..there is one problem: The buffer is a 20char but I can insert more than 20 char...why?
Because your program can't stop someone inputting more than 20 chars; all it can do is limit that it doesn't overflow the buffer which it already does - read() doesn't read more than the requested bytes. It only appears as if a read() call is reading more than size (20) but acutally read() reads only (upto) 20 chars and the rest is read in the next iteration.
No matter what method you use to read input and/or increase buffer size, this problem of "extra input" is always going to be there.
What you can do instead is check if if len is 20 and buffer[19] is not \n:
else {
write(STDERR_FILENO, buffer, len);
/* Read out the left over chars. */
if (len == 20 && buffer[19] != '\n') {
char c;
do {
read(STDIN_FILENO, &c, 1); /* left out the error checking */
} while (c != '\n');
}
Or increase the buffer size, say, to 512 bytes and then only look at the first 20 bytes that you're interested in.
Note: Add error checking for all read() and write() calls.
You're not allocating enough memory for your buffer. You always need 1 more to store the NUL terminating character. And you also need to remember to add that NUL character to the end of the string read in by read as it won't do it for you.
When you get an error, you should exit the loop.
#define BUF_SIZE (20)
int main() {
char *buffer = malloc(sizeof(char)*(BUF_SIZE+1));
int len = 0;
do {
len = read(STDIN_FILENO, buffer, BUF_SIZE);
if(len == -1) {
write(STDERR_FILENO, "Error read\n", 10);
break;
} else {
buffer[len]='\0';
write(STDERR_FILENO, buffer, len);
}
} while(strncmp(buffer,"fine\n", 5));
free(buffer);
return 0;
}
You'll probably also find that the strncmp(buffer,"fine\n", 5) isn't going to work as you'd need to process the read in string to handle lines of input as read will happily read in multiple lines at a time (assuming they all fit in the buffer size).
I am having trouble sending a string, one char at a time through sock_stream connection. The reason for this is that I am attempting to send multiple strings which are nearly 70000 characters at a time. It seems that the write function I was attempting to use requires a string.
for(i=0;i<BUF_SIZE;i++)
{
write(sockfd,plaintext[i],1);
if(plaintext[i]=='0')
break;
}
write(sockfd,'^',sizeof(char));
Also, how would I read this? Here is how I was attempting it.
int read_line(int fd,char message[])
{
size_t message_len=0;
while (message_len<BUF_SIZE)
{
char c;
int ret = read(fd, &c, 1);
if (ret < 0)
{
message[message_len] = 0;
return len; // EOF reached
}
if (c == '^')
{
read(fd,&c,1);
message[message_len] = 0;
return message_len; // EOF reached
}
data[len++] = c;
}
}
How would I implement this? Thank you.
The signature of write api is:
int write(int fd, const void *buf, size_t nbyte);
So what you can do something like:
#define BUF_SIZE 70000
char *buf = (char*)malloc(BUF_SIZE);
int written = 0;
int wrote;
if (buf)
memset(buf, 1, BUF_SIZE);
else
return written;//some error code
while (written < BUF_SIZE)
{
wrote = write(fd, buf, BUF_SIZE);
if (wrote < 0)
return written;
written += wrote;
}
Similarly you should try to do bulk read, as reading one char at a time is too slow unless you have a very valid reason. Each time you do write or read, its system call and they are costly.
So for read you can try something like
int read_bytes = read(fd, buf, BUF_SIZE);
and read_bytes will have the exact value of how much you have read.
Then do parse_buf(buf) in which you can find the tag you are looking for and then save the rest for the future in case you get more data, else if you get less data, then call read again.
You need change line
write(sockfd,plaintext[i],1);
to
write(sockfd,&plaintext[i],1);
Additionally, you can use
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
to enable TCP_NODELAY option.
I am learning C and I have been trying to read a file and print what I just read. I open the file and need to call another function to read and return the sentence that was just read.
My function will return 1 if everything went fine or 0 otherwise.
I have been trying to make it work for a while but I really dont get why I cant manage to give line its value. In the main, it always prints (null).
The structure of the project has to stay the same, and I absolutely have to use open and read. Not fopen, or anything else...
If someone can explain it to me that would be awesome.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define BUFF_SIZE 50
int read_buff_size(int const fd, char **line)
{
char buf[BUFF_SIZE];
int a;
a = read(fd, buf, BUFF_SIZE);
buf[a] = '\0';
*line = strdup(buf);
return (1);
}
int main(int ac, char **av)
{
char *line;
int fd;
if (ac != 2)
{
printf("error");
return (0);
}
else
{
if((fd = open(av[1], O_RDONLY)) == -1)
{
printf("error");
return (0);
}
else
{
if (read_buff_size(fd, &line))
printf("%s\n", line);
}
close(fd);
}
}
Here:
char buf[BUFF_SIZE];
int a;
a = read(fd, buf, BUFF_SIZE);
buf[a] = '\0';
if there are more characters than BUFF_SIZE available to be read, then you will fill your array entirely, and buf[a] will be past the end of your array. You should either increase the size of buf by one character:
char buf[BUFF_SIZE + 1];
or, more logically given your macro name, read one fewer characters:
a = read(fd, buf, BUFF_SIZE - 1);
You should also check the returns from strdup() and read() for errors, as they can both fail.
read(fd, buf, BUFF_SIZE); //UB if string is same or longer as BUFF_SIZE
u need +1 byte to store 0, so use BUFF_SIZE - 1 on reading or +1 on array allocation...also you should check all returned values and if something failed - return 0
Keep it simple and take a look at:
https://github.com/mantovani/apue/blob/c47b4b1539d098c153edde8ff6400b8272acb709/mycat/mycat.c
(Archive form straight from the source: http://www.kohala.com/start/apue.tar.Z)
#define BUFFSIZE 8192
int main(void){
int n;
char buf[BUFFSIZE];
while ( (n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
if (write(STDOUT_FILENO, buf, n) != n)
err_sys("write error");
if (n < 0)
err_sys("read error");
exit(0);
}
No need to use the heap (strdup). Just write your buffer to STDOUT_FILENO (=1) for as long as read returns a value that's greater than 0. If you end with read returning 0, the whole file has been read.
Here is example code:
int nbajt; int buf[];
// we opened file and get descriptor fd
while ((nbajt = read(fd, buf, 5)) > 0) {
if (write(fd2, buf, nlbajt) == -1) {
perror("ERROR");
exit(1);
}
}
I don't understand how it is working when we use while loop. How many times this loop will proceed? (times of the lengs of buf?). Will nbajt has only values of 1 or 0 + buf file position will be changing 1 place after each loop step? So in first step we have nlbajt = 1 and we take buf first position char and then write it to fd2?. On the end we have nlbajt==0 so it means it's end of file? I would be grateful for checking if i am wrong.My main concern is how nbajt value is changing. How it is diffrent for this attitude:
nbajt = read(fd, buf, 5));
write(fd2, buf, sizeof(a));
The read() has the below prototype:
int read( int handle, void *buffer, int nbyte );
It returns number of bytes successfully read . 0 when EOF is reached.-1 when there is an error.
Yes nlbajt = 0 means EOF here.