I'm having problems with writing to shared memory segment. Here's the code:
EDIT: after I removed that == (mistake), now I'm getting Bus Error (Core Dumped), here's the edited code:
// Struct for data from shared memory
typedef struct {
pthread_mutex_t shared_mutex;
int last_used_job_id;
} shared1;
static void *job_generator(void *param)
{
int J = *((int *) param);
shared1 *shd;
int shm;
int job_id;
// Open shared memory, don't create it if doesn't exist
shm = shm_open("/lab5", O_RDWR, 00600);
// Check
if (shm == -1) {
// Open shared memory, create it if doesn't exist (O_CREAT)
shm = shm_open(q_name, O_RDWR | O_CREAT, 00600);
// Map space for struct
shd = mmap(NULL, sizeof(shared1), PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
if (shd == (void *) -1) {
perror ( "mmap" );
exit(1);
}
// Initialize mutex
if (pthread_mutex_init(&(shd->shared_mutex), NULL) != 0)
{
printf("Mutex initialization failed!\n");
exit(1);
}
}
else
{
// Map space for struct
shd = mmap(NULL, sizeof(shared1), PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
if (shd == (void *) -1) {
perror ( "mmap" );
exit(1);
}
}
// Lock mutex
pthread_mutex_lock(&(shd->shared_mutex));
job_id = shd->last_used_job_id + 1;
shd->last_used_job_id = job_id + J;
printf("a: %d\n", shd->last_used_job_id);
return NULL;
}
it's caused by any of the instructions which are using shd, so any of these:
// Lock mutex
pthread_mutex_lock(&(shd->shared_mutex));
job_id = shd->last_used_job_id + 1;
shd->last_used_job_id = job_id + J;
printf("a: %d\n", shd->last_used_job_id);
I think this is where your problem lies:
shd == mmap(NULL, sizeof(shared1), PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
You're comparing shd to the return value of mmap with '=='. I think you meant to use a single '=' which would assign the return value to shd.
Related
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 have a structure
struct {
int size;
char *data;
}tmp_buf;
Now i want to allocate memory to the structure in shared memory (mmap-ed location)
i have a pointer "tp" of type "tmp_buf" in my main()
When i try to use strncpy() something at location "tp->data" it gives a segmentation fault.
I have mmap-ed shared memory of size (sizeof(struct tmp_buf) + length_of_data)
This is the code i'm running:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/mman.h>
void * create_shared_memory(char *name, int size) {
int *ptr;
int ret;
int fd = shm_open (name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd == -1) {
perror ("shm_open error!");
exit (1);
}
ret = ftruncate (fd, sizeof (size));
if (ret == -1) {
perror ("ftruncate error!");
exit (2);
}
ptr = mmap(0, sizeof (size), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) {
perror ("shm-mmap error!");
exit (3);
}
return ptr;
}
typedef struct {
int size;
char *data;
}tmp_buf;
int main (int argc, char **argv)
{
tmp_buf *buf_ptr;
if(argc != 2)
{
perror("Error: Incorrect number of arguments passed\n");
exit(EXIT_FAILURE);
}
int max_buffers = atoi(argv[1]);
buf_ptr = (struct tmp_buf*)create_shared_memory("my_shm_buffer",sizeof(tmp_buf) + max_buffers*1024);
printf("Shared Memory Location: %p\n", buf_ptr);
printf("Shared Memory size: %d\n", buf_ptr->size);
printf("Shared Memory data: %s\n", buf_ptr->data);
buf_ptr->size =1;
printf("Shared Memory size: %d\n", buf_ptr->size);
printf("SIZEOF(int) =%d SIZEOF(char*) = %d\n",sizeof(int), sizeof(char*));
printf("Shared Memory size address: %p\n", (void*)&(buf_ptr->size));
printf("Shared Memory data address: %p\n", (void*)&(buf_ptr->data));
strncpy(buf_ptr->data,"Hello\n", 6);
printf("Shared Memory data: %s\n", buf_ptr->data);
return 0;
}
Output i am seeing is something like this :
Shared Memory Location: 0x7ffff7ff6000
Shared Memory size: 0
Shared Memory data: (null)
Shared Memory size: 1 (After t->size = 1)
Shared Memory size address: 0x7ffff7ff6000
Shared Memory data address: 0x7ffff7ff6008
Segmentation fault (core dumped) (After strncpy("Hello\n",tp->data, 6))
Have you tried
strncpy(buf_ptr->data, "Hello\n\0", 7);
You should use strncpy with (dest, src, len) and not (src, dest, len)
The C library function char *strncpy(char *dest, const char *src, size_t n) copies up to n characters from the string pointed to, by src to dest. In a case where the length of src is less than that of n, the remainder of dest will be padded with null bytes.
The most obvious problem is demonstrated with this line:
ret = ftruncate (fd, sizeof (size));
sizeof(size) is not going to be very much as it'll be whatever sizeof(int) gives you. To make it the size you want you just pass in size as is like so...
ret = ftruncate (fd, size);
You then repeat the same problem with this line which should also have size instead of sizeof(size)
ptr = mmap(0, sizeof (size), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
It's probably worth changing the function declaration to make size be of type size_t and have it return a tmp_buf *. Casting the void * returned won't automagically cause it to populate buf_ptr with valid values. End result should look like
tmp_buf* create_shared_memory(char *name, size_t size) {
tmp_buf *ptr;
int ret;
int fd = shm_open (name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd == -1) {
perror ("shm_open error!");
exit (1);
}
ret = ftruncate (fd, size);
if (ret == -1) {
perror ("ftruncate error!");
exit (2);
}
ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) {
perror ("shm-mmap error!");
exit (3);
}
ptr->size = size;
ptr->data = ((char *) ptr) + sizeof(ptr->size);
return ptr;
}
Description :
I have a project directory named "Projet" which contain two directory named "Serveur" and "Client".
(1) Serveur contains serveur.c (2) Client contains client.c
Referenting to the man, I choose as a name : "/shm_request_stack".
Source files description :
serveur.c :
#define SHM_REQUEST "/shm_request_stack"
int main(void) {
sem_t shm = open_shm(SHM_REQUEST,
O_RDWR | O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR);
unlink_shm(SHM_REQUEST);
size_t memsize = sizeof(int);
setsize_shm(shm, memsize);
int * ptr = project_shm(shm, memsize);
*ptr = 0;
while(*ptr == 0);
printf("Client modify the value\n");
}
client.c :
#define SHM_REQUEST "/shm_request_stack"
int main(void) {
sem_t shm = open_shm(SHM_REQUEST,
O_RDWR,
S_IRUSR | S_IWUSR);
unlink_shm(SHM_REQUEST);
size_t memsize = sizeof(int);
int * ptr = project_shm(shm, memsize);
*ptr = 1;
}
Envelope functions
int open_shm(char *name, int oflag, mode_t mode) {
int shm = shm_open(name, oflag, mode);
if (shm == -1) {
fprintf(stderr, "Error while opening %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
return shm;
}
void unlink_shm(char *name) {
if (shm_unlink(name) == -1) {
perror("sem_unlink");
exit(EXIT_FAILURE);
}
}
void setsize_shm(int shm, size_t size) {
if (ftruncate(shm, size) == -1) {
perror("ftruncate");
exit(EXIT_FAILURE);
}
}
void * project_shm(int shm, size_t size) {
int *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
if (ptr == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
return ptr;
}
Problems :
The client can't find the named shm create by the server.
I tried to found the shared memory with ipcs -m but I've not.
I try to modify the value from the server and it's works so the memory exist.
How can I successfully open the shm from the client ?
You appear to be deleting the shared object immediately after creating it (unlink).
It is a bit like a file. If you have an open reference to the object then it is retained, but the unlink removes the name. That is why the server can still write to the object after the unlink (she is still in scope), but the client cannot open the object by name.
The critical words in the doc you quote are : "all open and map references" - what you can't do is create a new reference after the unlink.
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];
};
I am trying to share some data between parent and child process. For the first time I can write and read data to shared memory. However if I want to write one more data, I got truncate error. I know something is wrong with my code. I feel like I need to implement base address part but I don't know how to do it.
void *attach_shmem(int shmem_fd, int object_size){
void *addr;
/* resize it to something reasonable */
if (ftruncate(shmem_fd, object_size) == -1){
perror("failed to resize shared memory object\n");
exit(EXIT_FAILURE);
}
addr = mmap(base, object_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmem_fd, 0);
if (addr == MAP_FAILED){
perror("failed to map shared memory object\n");
exit(EXIT_FAILURE);
}
return addr;
}
void *map_shmem(char *path, int object_size){
int shmem_fd;
/* open one that has already been created */
shmem_fd = shm_open(path, O_RDWR, S_IRUSR | S_IWUSR);
if (shmem_fd == -1){
fprintf(stdout, "failed to open shared memory object\n");
exit(EXIT_FAILURE);
}
return attach_shmem(shmem_fd, object_size);
}
void add_ip_to_shared_memory(char *ip, int val, int num)
{
sem_t *sem = sem_open("/basag_sem", 0);
struct SharedMem *node;
char ip_binary[100];
void *addr;
strcpy(ip_binary, transform_ip_to_bits(ip));
node = malloc(sizeof(struct SharedMem));
strcpy(node->ip, strndup(ip_binary, num));
node->val = val;
//semaphore block
sem_wait(sem);
//add node to shared memory
addr = map_shmem("gungor_shmem", sizeof(*node));
memcpy(addr, node, sizeof(*node));
base = addr;
sem_post(sem);
free(node);
//semaphore release
//write_to_screen(node->ip);
setbuf(stdout, NULL);
}