shmat() - perror returns invalid argument - c

I tried to attach a char vector to a shared memory: shmget() is ok but shmat() returns an error.
This is my code:
...
...
#define TXTSZ 512
---main---
char *address;
int shm_id;
...
if(shm_id = shmget(IPC_PRIVATE, TXTSZ*sizeof(char), IPC_CREAT | 0666) == -1){
perror("Error shmget");
}
...
if((address = (char *)shmat(shm_id, NULL, 0)) == (char *) -1){
perror("Error shmat");
}
...
...

Classic mistake (usually made with open()). You're setting shm_id to the result of the comparison, not the ID returned by shmget.
You need parentheses around the assignment.
if((shm_id = shmget(IPC_PRIVATE, TXTSZ*sizeof(char), IPC_CREAT | 0666)) == -1){

Related

mmap to fix address fails

I want to map a file stored in ramdisk to a fixed address, but mmap fails.
What mistake I am doing? Is there any other method to do this?
int fd = open("/mnt/tmpfs/hello.txt",
(O_RDONLY),
(S_IRWXU | S_IRWXG | S_IRWXO) );
if ( fd < 0 )
perror("open() error");
struct stat buf;
fstat(fd, &buf);
void * address = aligned_alloc(PGSIZE, buf.st_size)
void *new_address = mmap(address,
buf.st_size,
PROT_READ,
(MAP_SHARED|MAP_FIXED),
fd,
0);
if (new_address != address) {
perror("mmap failed!")
}

How to detect which piece of my code is generating "Fatal error: glibc detected an invalid stdio handle" error?

I'm trying to code a simple program to copy a file into another using 2 processes.
I want to use shared memory to open both files and get a piece of shared memory of 1Byte to be used as exchange memory in a mutually exclusive way.
So the main process should open both files and put them in shared memories;
fork twice, I obtain 2 processes A and B.
Process A should read 1 byte of the first file, put it in the shared exchange memory and unlock the mutex for process B.
Process B should copy the file from the shared exchange memory and put it in its file and unlock the mutex for process A.
And so on.
#define SIZE 4096
void reader_process(FILE* fptr,char*exch, sem_t*mut){
while(1){
sem_wait(mut);
*exch = (char) getc(fptr);
sem_post(mut+1);
}
}
void writer_process(FILE* fptr,char*exch, sem_t*mut){
if(*exch == EOF){
printf("done\n");
exit(0);
}
while(1){
sem_wait(mut);
putc((int)*exch,fptr);
sem_post(mut-1);
}
}
int main(int argc, char *argv[]){
FILE* shared_f_ptr[2];
pid_t pid;
//2 files name.
char *files[2];
int fd[2];
//open files.
files[0] = argv[1];
printf("%s\n",files[0]);
FILE* fpointer1 = fopen(files[0],"r+");
if (fpointer1 == NULL){
perror("fopen\n");
exit(-1);
}
fd[0] = fileno(fpointer1);
files[1] = argv[2];
printf("%s\n",files[1]);
FILE* fpointer2 = fopen(files[1],"r+");
if (fpointer2 == NULL){
perror("fopen\n");
exit(-1);
}
fd[1] = fileno(fpointer2);
//shared File pointers.
shared_f_ptr[0] = (FILE*)mmap(NULL, SIZE*sizeof(char),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
fd[0], 0);
if (shared_f_ptr[0] == MAP_FAILED){
perror("mmap\n");
exit(-1);
}
shared_f_ptr[1] = (FILE*)mmap(NULL, SIZE*sizeof(char),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
fd[1], 0);
if (shared_f_ptr[1] == MAP_FAILED){
perror("mmap\n");
exit(-1);
}
//shared mem for 1B exchange.
char *shared_exchange = (char*)mmap(NULL, sizeof(char),
PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS,
-1, 0);
if (shared_exchange == MAP_FAILED){
perror("mmap\n");
exit(-1);
}
//mutex.
sem_t *mut = (sem_t*)mmap(NULL, 2*sizeof(sem_t),
PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS,
-1, 0);
sem_init(&mut[0],1,0);
sem_init(&mut[1],1,0);
//fork.
pid = fork();
if (pid == 0) {
reader_process(shared_f_ptr[0],
shared_exchange, &mut[0]);
}
if (pid == -1){
perror("fork\n");
exit(-1);
}
else pid = fork();
if (pid == 0) writer_process(shared_f_ptr[1],
shared_exchange, &mut[1]);
if (pid == -1){
perror("fork\n");
exit(-1);
}
else{
sem_post(&mut[0]);
}
}
I don't expect the error i am getting Fatal error: glibc detected an invalid stdio handle but i don't really know how to find what's causing the problem.
Don't do this:
//shared File pointers.
shared_f_ptr[0] = (FILE*)mmap(NULL, SIZE*sizeof(char),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
fd[0], 0);
if (shared_f_ptr[0] == MAP_FAILED){
perror("mmap\n");
exit(-1);
}
shared_f_ptr[1] = (FILE*)mmap(NULL, SIZE*sizeof(char),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
fd[1], 0);
if (shared_f_ptr[1] == MAP_FAILED){
perror("mmap\n");
exit(-1);
}
Use this instead:
shared_f_ptr[0] = fpointer1;
shared_f_ptr[1] = fpointer2;
Don't use the file descriptors underlying each FILE. Instead, simply use the FILE itself.
Also, instead of using fpointer1 and fpointer2, just use shared_f_ptr[0] and shared_f_ptr[1].
This is a possible definition of the FILE structure:
typedef struct _IO_FILE
{
int __fd;
int __flags;
int __unget;
char *__buffer;
struct {
size_t __orig;
size_t __size;
size_t __written;
} __bufsiz;
fpos_t __fpos;
} FILE;
As you can see, it's a structure, not just a flat pointer.

I am receiving "shmat: permission denied" when attempting to attach to shared memory. Why?

I'm having a little trouble with shared memory, and could use a little guidance if someone could point me in the right direction.
// Allocate Shared Memory
key_t key = 56789;
int shmid;
char* shm_address;
int* value;
// Reserve the memory
if (shmid = shmget(key, sizeof(int), IPC_CREAT | 0777) < 0)
{
perror("shmget was unsuccessful");
exit(1);
}
else
{
printf("\nMemory created successfully:%d\n", shmid);
}
// Attach to memory address
if ( (shm_address = shmat(shmid, NULL, 0)) == (char *)-1 )
{
perror("shmat was unsuccessful");
exit(1);
}
else
{
printf ("shared memory attached at address %p\n", shm_address);
}
I then do some process management, call shmdt(shm_address), and finally cleanup with shmctl. But I never reach that part of the code.
I get this as output:
Memory created successfully:0
shmat was unsuccessful: Permission denied
I just don't understand why shmat is failing to attach? When I call the ipcs command after execution, my memory is allocated, so I'm fairly confident that shmget is working. Could anyone point me in the right direction? Thanks.
Precedence error:
if (shmid = shmget(key, sizeof(int), IPC_CREAT | 0777) < 0)
This assigns shmget(key, sizeof(int), IPC_CREAT | 0777) < 0 (i.e. 0 or 1) to shmid. You want
if ((shmid = shmget(key, sizeof(int), IPC_CREAT | 0777)) < 0)

ftruncate() invalid arguement error

I just started learned about shared memory and we are suppose to create an object of shared memory for my assignment, but I keep getting an error when I run my program.
The error comes from the ftruncate() function and it keeps telling me its an invalid argument, here's my code segment for the shared memory:
struct container* rPtr;
int fd;
/* Creates shared memory object and sets it size */
fd = shm_open("/collatzRegion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd == -1)
{ perror("shm_open");
return 1;
}
if ((ftruncate(fd, sizeof(struct container))) == -1)
{ perror("ftruncate");
return 1;
}
/* Maps shared memory object */
rPtr = mmap(NULL, sizeof(struct container), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if ( rPtr == MAP_FAILED)
{ perror("mmap");
return 1;
}
and my structure, that is defined before my main(), is:
/* Defines "structure" of shared memory */
#define MAX_LEN 10000
struct container
{ int length;
int buf[MAX_LEN];
};

mremap function failed to allocate new memory

I have write the following code , but the code is still fiven me EEERROR message , which tells that the mremap failed to extend the memory.
int main()
{
int size_of_mem = 1024
int fd = shm_open("/myregion", O_CREAT | O_RDWR, S_IRWXO | S_IRUSR | S_IWUSR);
if (fd == -1)
printf("ERROR in shm_open \n") ;
if (ftruncate(fd, size_of_mem) == -1)
printf("ERROR in ftruncate \n") ;
int shm_address = mmap(0 , size_of_mem , PROT_READ | PROT_WRITE | PROT_EXEC ,MAP_SHARED , fd , 0) ;
if (shm_address == MAP_FAILED)
{
printf("Error mmapping the file \n");
exit(EXIT_FAILURE);
}
int temp = mremap(shm_address , size_of_mem ,4000 , MREMAP_MAYMOVE) ;
if( temp < 0)
{
printf("EEEEEEEERROR\n") ;
}
return 0 ;
}
There are a couple of things wrong here.
First, mmap() and mremap() return a void* pointer, which you must not just cast to an int.
Second, the mremap() man page states:
RETURN VALUE
On success mremap() returns a pointer to the new virtual memory area. On error, the value MAP_FAILED (that is, (void *) -1) is returned, and errno is set appropriately.
So your check temp < 0 is wrong. It should be temp == (void*)-1. It is entirely possible that mremap() returns a valid pointer on success that is smaller than zero when cast to an int.
Third, both mmap() and mremap() set the errno (man page) variable when an error occurs. You can read that to get more information about what exactly went wrong. To just output a text error message use the perror() function (man page). Note that you have to #include <errno.h> for that.
Fourth, if you detect an error condition, you always print a message, but you mostly allow execution to continue. That doesn't make sense. If shm_open() failed, you want to return immediately (or call exit(EXIT_FAILURE)). None of the following functions will work if you couldn't even open the SHM file.
Thus, my cleaned up version looks like this:
#include <error.h>
int main()
{
int size_of_mem = 1024;
int fd = shm_open("/myregion", O_CREAT | O_RDWR,
S_IRWXO | S_IRUSR | S_IWUSR);
if (fd == -1)
{
perror("Error in shm_open");
return EXIT_FAILURE;
}
if (ftruncate(fd, size_of_mem) == -1)
{
perror("Error in ftruncate");
return EXIT_FAILURE;
}
void *shm_address = mmap(0, size_of_mem,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_SHARED, fd, 0);
if (shm_address == MAP_FAILED)
{
perror("Error mmapping the file");
return EXIT_FAILURE;
}
void *temp = mremap(shm_address, size_of_mem, 4000, MREMAP_MAYMOVE);
if(temp == (void*)-1)
{
perror("Error on mremap()");
return EXIT_FAILURE;
}
return 0;
}
Note:
Correct data types (void*), correct error checking for mremap(), usage of perror() to print more informative error messages, error paths ending execution of the function.
Correct/consistent indentation.
No spaces before , in function calls.

Resources