C Linux shared memory error - ftruncate - c

I'm trying to open a shared mem file and write into it. The problem is that ftruncate is returning -1 .
Here is my code:
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include<sys/mman.h>
#include<sys/stat.h>
#include <fcntl.h>
int main(void) {
int fd;
fd=shm_open("/shmem-m", O_CREAT,0777);
printf("%d\n",fd);
int a=ftruncate(fd, 1024);
printf("%d\n",a);
void* addr=mmap(NULL, 1024, PROT_READ|PROT_WRITE, MAP_SHARED,fd, 0);
char* msg= "hola mundo!";
memcpy(addr,msg,strlen(msg));
exit(EXIT_SUCCESS);
//return 0;
}
The output is:
3
-1
Segmentation fault
Any ideas? Thank you very much

The problem is that POSIX requires the file to be opened in write mode for a call to ftruncate to succeed as stated in the ftruncate man page.
So the call to shm_open becomes shm_open("/shmem-m", O_CREAT | O_RDWR, 0777), with the O_RDWR flag set (shm_open man page).

Related

Mapped file on Cygwin continuing to cause SIGBUS even after a call to ftruncate that fills that page

I'm trying to mmap a page-size-rounded file to an area larger than the file size and ftruncate it when one of the traling pages causes a SIGBUS so that the SIGBUS no longer happens.
This works great on Linux and MacOS, but on Cygwin I keep getting a SIGBUS even after a successful growing ftruncate.
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
void perrorAndExit(char const *Ctx){ perror(Ctx); _exit(1); }
int main(){
long pgsz = sysconf(_SC_PAGESIZE);
int fd = open("TMPFILE", O_RDWR|O_CREAT,0640);
if(0>fd) perrorAndExit("open");
if(ftruncate(fd,pgsz*1)) perrorAndExit("truncate 1 pgsz");
char *m;
if(MAP_FAILED==(m = mmap(0,pgsz*10,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0))) perrorAndExit("mmap");
memset(m,'=',pgsz);
strcpy(m,"hello, world\n");
if(ftruncate(fd,pgsz*2)) perrorAndExit("truncate 2 pgsz");
strcpy(m+pgsz,"what is up?\n"); //still SIGBUSes on Cygwin
}
Are there any workarounds for this other than starting with a larger file or creating a new mapping after the second truncate?

Segmentation fault setup semaphore function

I got the shared_memory.c file where I'm declaring my functions. One of the functions will be setupSemaphoreRead().
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <fcntl.h>
#include "shared_memory.h"
//more code...
int setupSemaphoreRead(){
sem_unlink(SEM_CONSUMER_FNAME);
sem_unlink(SEM_PRODUCER_FNAME);
sem_t *sem_prod = sem_open (SEM_PRODUCER_FNAME, O_CREAT | O_EXCL, 0666, 0);
if (sem_prod == SEM_FAILED) {
perror("sem_open/producer");
return -1;
}
sem_t *sem_cons = sem_open (SEM_CONSUMER_FNAME, O_CREAT | O_EXCL, 0666, 1);
if (sem_cons == SEM_FAILED) {
perror("sem_open/consumer");
return -1;
}
return 1;
}
//more code...
I got the signature declared at my header file
int setupSemaphoreRead();
//filenames for two semaphores
#define SEM_PRODUCER_FNAME "myproducer"
#define SEM_CONSUMER_FNAME "myconsumer"
In my main read program I'm trying to use the function in the fallowing way:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shared_memory.h"
...
sem_t *sem_cons;
sem_t *sem_prod;
setupSemaphoreRead();
...
I don't get any error when compiling the code, but when executing I got Segmentation fault (core dumped)
setupSemaphoreRead() assigns to sem_t * local variables. When it returns those variables are out of scope. It has no access to variables of the same name in the other scope. You need to study more how variable scopes work in C. A typical way to do what you're trying to do is have a function accept double-pointer arguments like:
int setupSemaphoreRead(sem_t** sem_cons, sem_t** sem_prod) {
*sem_cons = ...
..
and use it like:
sem_t* sem_cons;
sem_t* sem_prod;
int ret = setupSempahoreRead(&sem_cons, &sem_prod);
// Make sure to check the value of ret
You have
sem_t *sem_prod
both inside the function and inside main. In other words - they are different variables, i.e. the variables in main are not updated by the function.

Again a question about reading a directory file with C

How we can use C functions open/read/close properly in order to read a linux directory?. I notice serveral others asked this question before, about on reading directories in C, also that several ones suggest the use of readdir/opendir/closedir functions, I know, but RnK book (the C programming language) in fact define or introduces those readdir/opendir/closedir/ functions, the problem is that read() function "not read" properly directories; it returns -1 instead of the number of bytes readed. Is there any change into the actual read() C function that produces this or it is necesary modifications to read()?
Here is my example code:
#include <sys/types.h>
#include <unistd.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
int main(){
int fd;
size_t nbytes;
ssize_t bytes_read;
char buf[20];
fd=open(".",O_RDONLY,0);
nbytes = sizeof(buf);
bytes_read = read(fd, buf, nbytes);
printf("Buf size: %ld file descriptor: %d bytes readed:
%ld\n",nbytes,fd,bytes_read);
}
Compiling above code in ubuntu linux read gives bytes_read = -1.
Thanks in advance

Call to fdopendir() corrupts file descriptor

I stumbled upon a problem in a program I was working on. The following reproduces my issue:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
int fd, ret_fd;
DIR *dirp;
fd = open("./", O_RDONLY);
#if 1
if ((dirp = fdopendir(fd)) == NULL) {
perror("dirp");
return 1;
}
closedir(dirp);
#endif
ret_fd = openat(fd, "Makefile", O_RDONLY);
if (ret_fd == -1) {
perror("ret_fd");
return 1;
}
return 0;
}
Basically, the call to openat(), which has been preceeded by fdopendir(), fails with: Bad file descriptor. However, this does not happen if fdopendir() is omitted.
I know that fdopendir() makes internal use of the file descriptor, but shouldn't it revert any changes to it after calling closedir()?
What can I do to prevent openat() from failing in this case?
The POSIX description of fdopendir() says:
Upon calling closedir() the file descriptor shall be closed.
So the descriptor is likely to be closed by the time you call openat().
And this is from a typical Linux man page for fdopendir():
After a successful call to fdopendir(), fd is used internally by the
implementation, and should not otherwise be used by the application.

Unix/C: put a file into shared memory

Have a problem.
I have a file which contents look like number:error_description.
Now i need to put this file to shared memory (POSIX). If any contents are modified it should be saved to the base-file.
There is a need to search in the content in the shared memory (results will be sent to a client over a message queue).
How do I implement all this? First I thought I have to open (fopen("my_file", "r")) and then I have to create shared memory and mmap the file.
Can someone help me?
edit:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <semaphore.h>
/*
* \ /tmp/errors -> Error File
*/
#define MSGQ_HANDLER "/error_handler"
#define PATH_TO_FILE "/tmp/errors"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
int main(void) {
int fd = open(PATH_TO_FILE, O_RDWR);
struct stat file_stat;
fstat(fd, &file_stat);
printf("File size: %zd\n", file_stat.st_size);
char *byte_ptr = mmap(NULL, file_stat.st_size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if(byte_ptr == MAP_FAILED){
perror("error:");
}
while(1){
printf("%s\n", byte_ptr);
if(byte_ptr)
exit(1);
}
return EXIT_SUCCESS;
}
So far it is what I have now.
Read a line works.
How do I change the content?
Don't use fopen and forget about shared memory (the sh* API I mean). mmap is all that's needed.
Open your file with open and the right options (read/write). Then use mmap with the option MAP_SHARED. All changes in the file will be reflected directly and visible to all processes that map the same file. On Linux and Solaris (on other systems I don't know, but it is not guaranteed by POSIX or any standard) you can even access the file concurrently with read/write. It is a bad idea though.
Concurrent memory accesses from different processes will, of course, need synchronisation (mutex, semaphores etc.).

Resources