The following code fails when the buffer is on the stack, but succeeds when it's allocated on the heap. I tested it on RHEL 5.3 with a Raid drive. Is it possible to use O_DIRECT with stack buffers?
#define _GNU_SOURCE
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <malloc.h>
#define K 1024
#define ALIGNMENT (4*K)
#define RDSIZE (16*K)
#define BLOCKSIZE (512*K)
int main()
{
int flags = O_RDONLY | O_LARGEFILE;
int n = 0;
int fd = 0;
char* buf = (char *) memalign(ALIGNMENT, BLOCKSIZE);
//char buf[BLOCKSIZE] __attribute__((__aligned__(ALIGNMENT)));
assert(((long)buf) % ALIGNMENT == 0);
fd = open("test", flags | O_DIRECT);
if (fd < 0) {
perror("file open");
return -1;
}
n = read(fd, buf, RDSIZE);
if (n < 0) {
perror("file read");
return -1;
}
printf("%d\n", n);
close(fd);
}
UPDATE: Same code when compiled with Intel CC succeeds.
Check your stack size 512K is quite a lot.
If the problem is gcc misaligning buf, try this portable version instead:
char x_buf[BLOCKSIZE+PAGE_SIZE];
char *buf = buf + (PAGE_SIZE-1 & -(uintptr_t)x_buf);
Related
I was trying out some exercises with the C language, specifically open() and read(). However, I've reached an impasse when I try printing to STDOUT the contents of a a text file (text.txt) that I have in the same directory as the c file. The size in bytes get printed, but the contents of the file do not.
I allocated space according to the size of the file, and added "1" for the null terminator. The manual page for read() states that it reads the contents of the file into the second parameter (void* buff). What am I missing/doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char* argv[]){
int fd = open("text.txt", O_RDONLY);
if (fd == -1){
printf("%s\n", strerror(errno));
return -1;
}
else {
int func = lseek(fd, 0, SEEK_END);
printf("%d bytes in size\n", func);
char* ptr = (char*)malloc(sizeof(char)*func + 1);
read(fd, ptr, func);
printf("%s", ptr);
free(ptr);
}
close(fd);
return 0;
}```
You need to move back to the beginning of the file before the read.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char* argv[]){
int fd = open("text.txt", O_RDONLY);
if (fd == -1){
printf("%s\n", strerror(errno));
return -1;
}
else {
int size = lseek(fd, 0, SEEK_END);
printf("%d bytes in size\n", size);
char* ptr = (char *) malloc(sizeof(char) * size + 1);
lseek(fd, 0, SEEK_SET); // move back to the beginning
read(fd, ptr, size);
printf("%.*s", size, ptr);
free(ptr);
}
close(fd);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char* argv[]){
int fd = open("text.txt", O_RDONLY);
if (fd == -1){
printf("%s\n", strerror(errno));
return -1;
}
else {
int size = lseek(fd, 0, SEEK_END);
printf("%d bytes in size\n", size);
char* ptr = (char *) malloc(sizeof(char) * size + 1);
lseek(fd, 0, SEEK_SET); // move back to the beginning
read(fd, ptr, size);
printf("%.*s", size, ptr);
free(ptr);
}
close(fd);
return 0;
}
(venv) [ttucker#zim stackoverflow]$ cat text.txt
asdf
qwer
sdfg
(venv) [ttucker#zim stackoverflow]$ gcc -o print print.c
(venv) [ttucker#zim stackoverflow]$ ./print
15 bytes in size
asdf
qwer
sdfg
The following code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
int
main(int argc, char **argv)
{
char *p;
int shm_fd;
int error;
size_t len;
if ((shm_fd = shm_open("/somename", O_CREAT | O_RDWR, 0666)) < 0) {
perror("shm_open");
exit(1);
}
error = close(shm_fd);
if (error < 0) {
perror("close");
}
return 0;
}
Works fine on fedora22 x86_64, freebsd 10.2 x86_64. But it fails on OSX 10.10 with
close: Invalid argument
What is wrong with the call on OSX?
I have create a Linux Software RAID, with chunk size 4096B, and 4 disks.
Then, I'm trying to do write and read test on the RAID, say /dev/md0.
The following code is read test and BLOCK_SIZE is the amount I want to read. However, whenever I set it not power of 2, such as 3*4096, I will get an error after read, saying "Invalid Argument". And it is the same case with write.
As far as I can understand, read(2) and write(2) should be able to perform operation on any amount of bytes the user wants, so please help me with it and the code.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#define BLOCK_SIZE 8*4096 //bytes
#define BUFF_OFFSET 8*4096
int main(int argc, char *argv[]){
char device[64];
int fd;
void *buff;
int size; //bytes
int seek;
fd = open(argv[1], O_DIRECT | O_RSYNC | O_RDONLY);
posix_memalign(&buff, BUFF_OFFSET, BLOCK_SIZE);
int load;
seek = lseek(fd,0,SEEK_SET);
load = read(fd,buff,BLOCK_SIZE);
if (load < 0){
printf("Cannot read\n");
perror("because");
break;
}
else{
printf("%d\n",load);
}
close(fd);
return 0;
}
When I reach the line routerInfo->areaID, I got segment fault: 11 on that part.
It seem that I do not allocate the memory successfully.
I just do not know why.
Can any one solve this problem?
My header is like this:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include<memory.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <semaphore.h>
#include <time.h>
#include <signal.h>
#include <fcntl.h>
#include <stdbool.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#define QUEUE_SIZE 300
#define MAX_CONN 10
#define TYPE_ROUTE 1
#define TYPE_TERMINAL 2
#define CONN_INIT false
#define CONN_ESTB true
#define CSPORT 39246
struct localInfo{
char router_ID[16];
int helloTime;
int protocol_Version;
int update_Interval;
int area_ID;
int neighborNum;
};
//shared information struct
and My main function is:
#include "BasicHeader.h"
int shared_hello, shared_lsa, shared_ping, shared_data, shared_localInfo;//using shared memory
pid_t childpid;//using for child process
int main(){
printf("Starting router ... ");
sleep(1);
key_t keyForLocalInfo = ftok(".", 1);
shared_localInfo = shmget ( keyForLocalInfo , sizeof(struct localInfo) , IPC_CREAT) ;
if (shared_localInfo == -1) {perror("error creating");exit(1);}
printf("shared_localInfo: %d\n", shared_localInfo);
//creating the queue for shared_localInfo
system("ipcs -m");
//show the shm status
//creating the sharing memory finished
struct localInfo *routerInfo = (struct localInfo*) shmat (shared_localInfo, (void *)0, 0);
if (routerInfo == NULL) {
perror("shmat");exit(1);
}
routerInfo->area_ID = 0;
routerInfo->helloTime = 45;
routerInfo->neighborNum = 0;
routerInfo->protocol_Version = 1;
routerInfo->update_Interval = 180;
shmdt(routerInfo);
int err = 0;
if ((err = shmctl(shared_localInfo, IPC_RMID, 0) == -1))
perror("shmctl shared_localInfo");
}
Change the permissions on semget to allow access e.g.
shmget(keyForLocalInfo, sizeof(struct localInfo),
IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
Note that shmat returns a ptr set to -1, not NULL, and thus the error check was not catching the error. The code should have been
struct localInfo *routerInfo = (struct localInfo*) shmat (shared_localInfo, (void *)0, 0);
if (routerInfo == (void *) -1)
{
perror("shmat");
exit(1);
}
I am having problem debugging why n_bytes in read_from_fifo function in client.c doesn't correspond to the value written to the fifo. It should only write 25 bytes but it tries to read a lot more (1836020505 bytes (!) to be exact). Any idea why this is happening?
server.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#include <sys/stat.h>
typedef enum { false, true } bool;
//first read the int with the number of bytes the data will have
//then read that number of bytes
bool read_from_fifo(int fd, char* var)
{
int n_bytes;
if (read(fd, &n_bytes, sizeof(int)))
{
printf("going to read %d bytes\n", n_bytes);
if (read(fd, var, n_bytes))
printf("read var\n");
else {
printf("error in read var. errno: %d\n", errno);
exit(-1);
}
}
return true;
}
int main()
{
mkfifo("/tmp/foo", 0660);
int fd = open("/tmp/foo", O_RDONLY);
char var[100];
read_from_fifo(fd, var);
printf("var: %s\n", var);
return 0;
}
client.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
typedef enum { false, true } bool;
//first write to fd a int with the number of bytes that will be written afterwards
bool write_to_fifo(int fd, char* data)
{
int n_bytes = (strlen(data)) * sizeof(char);
printf("going to write %d bytes\n", n_bytes);
if (write(fd, &n_bytes, sizeof(int) != -1))
if (write(fd, data, n_bytes) != -1)
return true;
return false;
}
int main()
{
int fd = open("/tmp/foo", O_WRONLY);
char data[] = "some random string abcdef";
write_to_fifo(fd, data);
return 0;
}
Help is greatly appreciated. Thanks in advance.
The return value for an error from read(2) is -1, not 0. So your if statement for the first 4-byte read, at least, is wrong.
Did you verify if nbytes printed by read_from_fifo() function displayed the correct value ?
Just notice that on write(fd, data, n_bytes) you did not write the end of string char '\0', and whenever you read it by read(fd, var, n_bytes), you did not added a '\0' to the end of string just read, so the printf("var: %s\n", var); could display a not \0 ended string resulting unpredicted results.
I have found the solution myself.
The problem is a ')' believe it or not. The n_bytes variable is correct, the problem is that I am not writing that to the fifo.
this (write(fd, &n_bytes, sizeof(int) != -1))
should be this (write(fd, &n_bytes, sizeof(int)) != -1)
Thanks anyway for your answers.