How to share ck_list across processes? - c

I'm trying to use CK_LIST from http://concurrencykit.org/ across multiple processes but when I do, the values inside the list nodes are garbage. But the list values are correct when I use the list only from one process.
Here is an example of using CK_LIST in a struct with in a single process.
#include <stdio.h>
#include <stdlib.h>
#include <ck_queue.h>
struct shared_map
{
CK_LIST_HEAD(list, list_node) list;
};
struct list_node
{
void *data;
CK_LIST_ENTRY(list_node) list_entry;
};
int main(void)
{
struct list_node *node, *node2;
struct shared_map mapping = { .list = CK_LIST_HEAD_INITIALIZER(mapping->list) };
struct shared_map *map = &mapping;
node = malloc(sizeof(struct list_node));
if(node == NULL)
{
perror("malloc");
return -1;
}
CK_LIST_INIT(&map->list);
int rtrn = asprintf((char **)&node->data, "test");
if(rtrn < 0)
{
perror("asprintf");
return -1;
}
CK_LIST_INSERT_HEAD(&map->list, node, list_entry);
CK_LIST_FOREACH(node2, &map->list, list_entry)
{
printf("out: %s\n", node2->data);
}
return 0;
}
But when I try to use the list between two separate processes the value of node->data is garbage and causes the process using it to crash. Below is an example.
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <ck_queue.h>
struct shared_map
{
CK_LIST_HEAD(list, list_node) list;
};
struct list_node
{
void *data;
CK_LIST_ENTRY(list_node) list_entry;
};
static int create_shared(void **pointer, int size)
{
*pointer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
if(*pointer == MAP_FAILED)
{
perror("mmap:");
return -1;
}
return 0;
}
int main(void)
{
struct list_node *node, *node2;
struct shared_map mapping = { .list = CK_LIST_HEAD_INITIALIZER(mapping->list) };
struct shared_map *map = &mapping;
int rtrn = create_shared((void **)&map, sizeof(struct shared_map));
if(rtrn < 0)
{
printf("Can't create shared mapping\n");
return -1;
}
CK_LIST_INIT(&map->list);
pid_t pid;
pid = fork();
if(pid == 0)
{
/* Child. */
node = malloc(sizeof(struct list_node));
if(node == NULL)
{
perror("malloc");
return -1;
}
int rtrn = asprintf((char **)&node->data, "test");
if(rtrn < 0)
{
perror("asprintf");
return -1;
}
CK_LIST_INSERT_HEAD(&map->list, node, list_entry);
}
else if(pid > 0)
{
/* Parent. */
sleep(1); // Make sure child runs first.
CK_LIST_FOREACH(node2, &map->list, list_entry)
{
printf("out: %s\n", node2->data);
}
}
else
{
perror("fork");
return -1;
}
return 0;
}
CK_LIST is listed as a multi-reader single-writer linked list so I thought I only had to lock on writes not reads. So why does node->data become garbage when using it between processes as opposed to when used by a single process?

Fortunately, this has nothing to do with CK and just to do with where your memory is coming from.
Your allocation in the child comes from malloc and lives in the child's address space. The child and parent do not share the same address space (being separate processes), so your malloc(3)-obtained storage for the node and data are not at addresses within the parent's address space.
You need to allocate the memory for the node and node->data from some shared space as well. I made a minimal set of changes to the code to get it to work for demonstration purposes. Hopefully obviously, you'd want your API to be less fragile in terms of magic numbers to mmap.
#include <sys/mman.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ck_queue.h>
struct shared_map {
CK_LIST_HEAD(list, list_node) list;
};
struct list_node {
void *data;
CK_LIST_ENTRY(list_node) list_entry;
};
static int
create_shared(void **pointer, int size)
{
*pointer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
if (*pointer == MAP_FAILED) {
perror("mmap:");
return -1;
}
return 0;
}
int
main(void)
{
struct list_node *node, *node2;
struct shared_map mapping = { .list = CK_LIST_HEAD_INITIALIZER(mapping->list) };
struct shared_map *map = &mapping;
int rtrn = create_shared((void **)&map, sizeof(struct shared_map) + sizeof(struct list_node) + 5);
if (rtrn < 0) {
printf("Can't create shared mapping\n");
return -1;
}
CK_LIST_INIT(&map->list);
pid_t pid;
pid = fork();
if (pid == 0) {
/* Child. */
node = (struct list_node *)(map + 1);
node->data = node + 1;
memcpy(node->data, "test", 5);
CK_LIST_INSERT_HEAD(&map->list, node, list_entry);
} else if (pid > 0) {
/* Parent. */
sleep(1); // Make sure child runs first.
CK_LIST_FOREACH(node2, &map->list, list_entry) {
printf("out: %s\n", (char *)node2->data);
}
} else {
perror("fork");
return -1;
}
return 0;
}
Fundamentally, I just changed the size of the mmap to include space for the list_node and the C string attached to node->data and made the child set that up.

Related

Initializing array of struct in a struct after mmap

I have a custom queue implementation as below
struct Customer {
pid_t pid;
int priority;
int order;
};
typedef struct Customer Customer_t;
struct CustomerNode {
int next;
int filled;
Customer_t customer;
};
typedef struct CustomerNode CustomerNode_t;
struct CustomerQueue {
int front;
int rear;
int filledNodes;
CustomerNode_t nodes[NODE_SIZE];
};
typedef struct CustomerQueue CustomerQueue_t;
and I need to map a CustomerQueue_t *queue as shared memory object, shared between processes. When I mmap first then initialize the struct, it gives segmentation fault.
void initQueue() {
sharedQueue->front = 0;
sharedQueue->rear = 0;
sharedQueue->filledNodes = 0;
sharedQueue->nodes = {0};
for (int i = 0; i < NODE_SIZE; ++i) {
sharedQueue->nodes[i] = (CustomerNode_t) { .next = -1, .filled = 0, (Customer_t) {-1, -1, -1 } };
}
}
Mmap part
#define SHMQUEUE "SHMQUEUE"
...
CustomerQueue_t* sharedQueue;
int sharedQueueFd;
// open queue shared memory
sharedQueueFd = shm_open(SHMQUEUE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
failChecker(sharedQueueFd, "Failed to open shared memory");
failChecker(ftruncate(sharedQueueFd, sizeof(CustomerQueue_t)), "Failed to ftruncate");
// map pizza new shared memory
sharedQueue = mmap(NULL, sizeof(CustomerQueue_t*), PROT_READ | PROT_WRITE, MAP_SHARED, sharedQueueFd, 0);
if(sharedQueue == MAP_FAILED) {
perror("Failed mmap");
_exit(-1);
}
Here is the valgrind result when I changed sizeof(CustomerQueue_t) instead of its pointer.
How can I solve it

Receiving a Segmentation Fault when using this memory allocator

I am trying to implement a memory allocator which can be called by multiple processes at once, so I used shared memory to keep the information of the first and last memory block alocated, both are put in the first 32 bytes of the shared memory and after that I tried to just have a simple allocation from the getpagesize() offset in the shared memory to see if it works but I keep getting a Segmentation Fault when using it to allocate a simple integer variable and I cannot figure out why.
#include <unistd.h>
#include <string.h>
#include <pthread.h>
/* Only for the debug printf */
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
typedef char ALIGN[16];
union header {
struct {
size_t size;
unsigned is_free;
union header *next;
} s;
/* force the header to be aligned to 16 bytes */
ALIGN stub;
};
typedef union header header_t;
header_t *get_free_block(size_t size)
{
char shm_name[] = "memalloc";
int shm_fd;
shm_fd = shm_open(shm_name, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
if (shm_fd < 0)
{
perror(NULL);
return NULL;
}
size_t shm_size = 10 * getpagesize();
if (ftruncate(shm_fd, shm_size) == -1)
{
perror(NULL);
shm_unlink(shm_name);
return NULL;
}
char* shm_ptr = mmap(0, shm_size, PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (shm_ptr == MAP_FAILED)
{
perror(NULL);
shm_unlink(shm_name);
return NULL;
}
header_t *head;
if (shm_ptr)
head = (header_t*)shm_ptr;
else
head = NULL;
header_t *tail;
if (head)
tail = (header_t*)(shm_ptr + 16);
else
tail = NULL;
header_t *curr = head;
while(curr) {
/* see if there's a free block that can accomodate requested size */
if (curr->s.is_free && curr->s.size >= size)
return curr;
curr = curr->s.next;
}
return NULL;
}
void *malloc(size_t size)
{
char shm_name[] = "memalloc";
int shm_fd;
shm_fd = shm_open(shm_name, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
if (shm_fd < 0)
{
perror(NULL);
return NULL;
}
size_t shm_size = 10 * getpagesize();
if (ftruncate(shm_fd, shm_size) == -1)
{
perror(NULL);
shm_unlink(shm_name);
return NULL;
}
char* shm_ptr = mmap(0, 32, PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (shm_ptr == MAP_FAILED)
{
perror(NULL);
shm_unlink(shm_name);
return NULL;
}
header_t *head;
if (shm_ptr)
head = (header_t*)shm_ptr;
else
head = NULL;
header_t *tail;
if (head)
tail = (header_t*)(shm_ptr + 16);
else
tail = NULL;
size_t total_size;
void *block;
header_t *header;
if (!size)
return NULL;
header = get_free_block(size);
if (header) {
/* Woah, found a free block to accomodate requested memory. */
header->s.is_free = 0;
return (void*)(header + 1);
}
/* We need to get memory to fit in the requested block and header from OS. */
total_size = sizeof(header_t) + size;
int nr_pagesize = 1;
block = mmap(0, total_size, PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, nr_pagesize * getpagesize());
if (block == MAP_FAILED)
{
perror(NULL);
shm_unlink(shm_name);
return NULL;
}
header = block;
header->s.size = size;
header->s.is_free = 0;
header->s.next = NULL;
if (!head)
head = header;
if (tail)
tail->s.next = header;
tail = header;
return (void*)(header + 1);
}
Here is the test program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int *x = (int*)malloc(sizeof(int));
return 0;
}
The commands I used on terminal are:
gcc -o memalloc.so -fPIC -shared memalloc.c
export LD_PRELOAD=$PWD/memalloc.so
gcc helloworld.c -o hello
and after compiling the test program I get the Segmentation Fault.

How to fix " assignment makes pointer from integer without a cast [-Wint-conversion]"? C unix program

I'm writing this 2 programs but I recive this warning: " assignment makes pointer from integer without a cast [-Wint-conversion]".
I'm trying to compile these programs to other Machines, but I recive same problem.
What can I do?
//PROGRAM 1 (PRODUCTOR)
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdio.h>
#define SHMEMSIZE 4096
int main()
{
key_t key_mem=6868;
key_t key_sem=3232;
int id_mem;
int id_sem;
void *addr_mem;
struct sembuf param[1];
if(id_mem = shmget(key_mem,SHMEMSIZE,0) == -1)
{
printf("Errore1\n");
return -1;
}
if(addr_mem =shmat(id_mem,NULL,0) == (void *)-1)
{
printf("Errore2\n");
return -1;
}
if(id_sem = semget(key_sem,2,0)== -1)
{
perror("Errore3\n");
shmdt(addr_mem);
return -1;
}
while(1)
{
param[0].sem_num=1;
param[0].sem_op=-1;
param[0].sem_flg=0;
if(semop(id_sem,param,1)==-1)
{
printf("Errore6\n");
return -1;
}
printf("Scrivi messaggio: ");
if(scanf("%[^\n]", (char *)addr_mem) == 0)
*((char *)addr_mem) = '\0';
getc(stdin);
param[0].sem_num=0;
param[0].sem_op=1;
param[0].sem_flg=0;
if(semop(id_sem,param,1)==-1)
{
printf("Errore7\n");
return -1;
}
}
shmdt(addr_mem);
}
_____________________________________________________
//PROGRAM 2 (CONSUMER)
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdio.h>
#define SHMEMSIZE 4096
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
int main()
{
key_t key_mem=6868;
key_t key_sem=3232;
int id_mem;
int id_sem;
void *addr_mem;
union semun arg;
struct sembuf param[1];
if(id_mem = shmget(key_mem,SHMEMSIZE,IPC_CREAT|0666) == -1)
{
printf("Errore1");
return -1;
}
if(addr_mem =shmat(id_mem,NULL,0) == (void *)-1)
{
printf("Errore2");
shmctl(id_mem, IPC_RMID, NULL);
return -1;
}
if(id_sem = semget(key_sem,2,IPC_CREAT|0666)== -1)
{
printf("Errore3");
shmctl(id_mem, IPC_RMID, NULL);
shmdt(addr_mem);
return -1;
}
arg.val=0;
if(semctl(id_sem,0,SETVAL,arg)==-1)
{
printf("Errore4");
semctl(id_sem, -1, IPC_RMID,arg);
shmctl(id_sem, IPC_RMID, NULL);
shmdt(addr_mem);
return -1;
}
arg.val=1;
if(semctl(id_sem,1,SETVAL,arg)==-1)
{
printf("Errore5");
semctl(id_sem, -1, IPC_RMID, arg);
shmctl(id_sem, IPC_RMID, NULL);
shmdt(addr_mem);
return -1;
}
while(1)
{
param[0].sem_num=0;
param[0].sem_op=-1;
param[0].sem_flg=0;
if(semop(id_sem,param,1)==-1)
{
printf("Errore6");
return -1;
}
printf("Il messaggio scritto è: %s\n",(char *)addr_mem);
param[0].sem_num=1;
param[0].sem_op=1;
param[0].sem_flg=0;
if(semop(id_sem,param,1)==-1)
{
printf("Errore7");
return -1;
}
}
}
My program should simply allow a producer process to write on shared memory and the consumer process to read shared memory.
I first receive this "warning" and after that if I try to run the producer I get a "Segmentation Fault". I absolutely can't understand what's going on.
I suppose that the shared memory is not really created, in fact if I delete the line * ((char *) addr_mem) = '0'; I do not get the "Segmentation Fault", and it is clear that the "Scanf" is not writing anything.
IMO if(id_mem = shmget(key_mem,SHMEMSIZE,IPC_CREAT|0666) == -1) is very bad style, exactly for the problem you have. You forgot to add parantheses around the assignment. You compare the result of shmget with -1 and assign this result to id_mem.
Change it to if((id_mem = shmget(key_mem,SHMEMSIZE,IPC_CREAT|0666)) == -1) or even better
id_mem = shmget(key_mem,SHMEMSIZE,IPC_CREAT|0666);
if (id_mem == -1)
The next ifs have the same problem.

Content wrong inside mmap'ed memory (Kernelspace<>Userspace)

I implement a memory mapping via mmap. My Kernel module writes something into this memory and a userspace application read this. In short I allocate 0x10000 memory (with kcalloc on kernel side and with mmap on userspace side). Then I write something to the address offsets 0x0, 0xf00 and 0xf000 using memcpy. On kernelside I can read back the memory correctly. But on userspace side the content of the first 0x1000 Bytes are repetitive through the whole memory (16 times). But why?
Her comes the code of the kernel module:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/mm.h>
#define DEV_MODULENAME "expdev"
#define DEV_CLASSNAME "expdevclass"
static int majorNumber;
static struct class *devClass = NULL;
static struct device *devDevice = NULL;
#ifndef VM_RESERVED
# define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP)
#endif
struct mmap_info
{
char *data;
int reference;
};
static void
dev_vm_ops_open( struct vm_area_struct *vma )
{
struct mmap_info *info;
// counting how many applications mapping on this dataset
info = (struct mmap_info *)vma->vm_private_data;
info->reference++;
}
static void
dev_vm_ops_close( struct vm_area_struct *vma )
{
struct mmap_info *info;
info = (struct mmap_info *)vma->vm_private_data;
info->reference--;
}
static int
dev_vm_ops_fault( struct vm_area_struct *vma,
struct vm_fault *vmf)
{
struct page *page;
struct mmap_info *info;
info = (struct mmap_info *)vma->vm_private_data;
if (!info->data)
{
printk("No data\n");
return 0;
}
page = virt_to_page(info->data);
get_page(page);
vmf->page = page;
return 0;
}
static const struct vm_operations_struct dev_vm_ops =
{
.open = dev_vm_ops_open,
.close = dev_vm_ops_close,
.fault = dev_vm_ops_fault,
};
int
fops_mmap( struct file *filp,
struct vm_area_struct *vma)
{
vma->vm_ops = &dev_vm_ops;
vma->vm_flags |= VM_RESERVED;
vma->vm_private_data = filp->private_data;
dev_vm_ops_open(vma);
return 0;
}
int
fops_close( struct inode *inode,
struct file *filp)
{
struct mmap_info *info;
info = filp->private_data;
free_page((unsigned long)info->data);
kfree(info);
filp->private_data = NULL;
return 0;
}
int
fops_open( struct inode *inode,
struct file *p_file)
{
struct mmap_info *info;
char *data;
info = kmalloc(sizeof(struct mmap_info), GFP_KERNEL);
// allocating memory on the heap for the data
data = kcalloc(0x10000,sizeof(char),GFP_KERNEL);
if( data==NULL )
{
printk(KERN_ERR "insufficient memory\n");
/* insufficient memory: you must handle this error! */
return ENOMEM;
}
info->data = data;
printk(KERN_INFO " > ->data: 0x%16p\n",info->data);
memcpy(info->data, "Initial entry on mapped memory by the kernel module", 52);
memcpy((info->data)+0xf00, "Somewhere", 9);
memcpy((info->data)+0xf000, "Somehow", 7);
printk(KERN_INFO " > ->data: %c%c%c\n", // the output here is correct
*(info->data+0xf000+0),
*(info->data+0xf000+1),
*(info->data+0xf000+2));
/* assign this info struct to the file */
p_file->private_data = info;
return 0;
}
static const struct file_operations dev_fops =
{
.open = fops_open,
.release = fops_close,
.mmap = fops_mmap,
};
static int __init
_module_init(void)
{
int ret = 0;
// Try to dynamically allocate a major number for the device
majorNumber = register_chrdev(0, DEV_MODULENAME, &dev_fops);
if (majorNumber<0)
{
printk(KERN_ALERT "Failed to register a major number.\n");
return -EIO; // I/O error
}
// Register the device class
devClass = class_create(THIS_MODULE, DEV_CLASSNAME);
// Check for error and clean up if there is
if (IS_ERR(devClass))
{
printk(KERN_ALERT "Failed to register device class.\n");
ret = PTR_ERR(devClass);
goto goto_unregister_chrdev;
}
// Create and register the device
devDevice = device_create(devClass,
NULL,
MKDEV(majorNumber, 0),
NULL,
DEV_MODULENAME
);
// Clean up if there is an error
if( IS_ERR(devDevice) )
{
printk(KERN_ALERT "Failed to create the device.\n");
ret = PTR_ERR(devDevice);
goto goto_class_destroy;
}
printk(KERN_INFO "Module registered.\n");
return ret;
// Error handling - using goto
goto_class_destroy:
class_destroy(devClass);
goto_unregister_chrdev:
unregister_chrdev(majorNumber, DEV_MODULENAME);
return ret;
}
static void __exit
_module_exit(void)
{
device_destroy(devClass, MKDEV(majorNumber, 0));
class_unregister(devClass);
class_destroy(devClass);
unregister_chrdev(majorNumber, DEV_MODULENAME);
printk(KERN_INFO "Module unregistered.\n");
}
module_init(_module_init);
module_exit(_module_exit);
MODULE_LICENSE("GPL");
here comes the code of the application
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#define PAGE_SIZE (0x10000)
int main ( int argc, char **argv )
{
int fd;
char *address = NULL;
time_t t = time(NULL);
char *sbuff;
int i;
sbuff = (char*) calloc(PAGE_SIZE,sizeof(char));
fd = open("/dev/expdev", O_RDWR);
if(fd < 0)
{
perror("Open call failed");
return -1;
}
address = mmap( NULL,
PAGE_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED,
fd,
0);
if (address == MAP_FAILED)
{
perror("mmap operation failed");
return -1;
}
printf("%s: first userspace read\n",tbuff);
memcpy(sbuff, address,80);
printf("Initial message: %s\n", sbuff);
memcpy(sbuff, address+0xf00,80);
printf("Initial message: %s\n", sbuff);
memcpy(sbuff, address+0xf000,80);
printf("Initial message: %s\n", sbuff);
for(i=0; i<PAGE_SIZE; i++)
{
printf("%16p: %c\n",address+i, (char)*(address+i));
}
if (munmap(address, PAGE_SIZE) == -1)
{
perror("Error un-mmapping the file");
}
close(fd);
return 0;
}
and this is the output of the application:
0x7fe61b522000: I
0x7fe61b522001: n
0x7fe61b522002: i
0x7fe61b522003: t
0x7fe61b522004: i
0x7fe61b522005: a
0x7fe61b522006: l
...
0x7fe61b522f00: S
0x7fe61b522f01: o
0x7fe61b522f02: m
0x7fe61b522f03: e
0x7fe61b522f04: w
0x7fe61b522f05: h
0x7fe61b522f06: e
0x7fe61b522f07: r
0x7fe61b522f08: e
...
0x7fe61b523000: I
0x7fe61b523001: n
0x7fe61b523002: i
0x7fe61b523003: t
0x7fe61b523004: i
0x7fe61b523005: a
0x7fe61b523006: l
...
0x7fe61b523f00: S
0x7fe61b523f01: o
0x7fe61b523f02: m
0x7fe61b523f03: e
0x7fe61b523f04: w
0x7fe61b523f05: h
0x7fe61b523f06: e
0x7fe61b523f07: r
0x7fe61b523f08: e
...
0x7fe61b524000: I
0x7fe61b524001: n
0x7fe61b524002: i
0x7fe61b524003: t
0x7fe61b524004: i
0x7fe61b524005: a
0x7fe61b524006: l
...
It seems to me, that the repetition comes with the size of one page. But this makes no sense to me.
EDIT 1:
Add Somewhere to the output. Note: Only Somehow never occurs!
EDIT 2:
Corrected fault handler. This now considered the offset of the calling vmf. Now it runs like a charm. Thanks to Tsyvarev!
static int
dev_vm_ops_fault( struct vm_area_struct *vma,
struct vm_fault *vmf)
{
struct page *page;
struct mmap_info *info;
info = (struct mmap_info *)vma->vm_private_data;
if (!info->data)
{
printk("No data\n");
return 0;
}
page = virt_to_page((info->data)+(vmf->pgoff*PAGE_SIZE));
get_page(page);
vmf->page = page;
return 0;
}
But on userspace side the content of the first 0x1000`
0x1000 is a size of the page mapped with
page = virt_to_page(info->data);
get_page(page);
vmf->page = page;
Callback .fault of structure vm_operations_struct is called for every page (4096 bytes), which is accessed by the user but not mapped yet.
So your code just map first 4096 bytes (0x1000) of data to every page which user space accesses.

Shared semaphore in c in linux

Here is part of character function which sends data in range 256 to 1024 bytes to buffer
semaphore_p(semMutexAll);//critical section
int charByte =rand() % 768 + 256;
for(i=0 ; i<charByte ; i++)
semaphore_p(semBuff);//contor buffer overflow
semaphore_v(semMutexAll);
Here is part of function cpu whic reads 2 bytes from buffer in 10 miliseconds
while(1)
{
semaphore_v(semBuff);
semaphore_v(semBuff);
usleep(10000);
}
Here is semaphores
semBuff = semget((key_t)1234,1,0666|IPC_CREAT); //Gets shared memory Id --> 1234 key
semChar = semget((key_t)1235,1,0666|IPC_CREAT);
semImage = semget((key_t)1236,1,0666|IPC_CREAT);
semAudio = semget((key_t)1237,1,0666|IPC_CREAT);
semVideo = semget((key_t)1238,1,0666|IPC_CREAT);
semMutexCpu = semget((key_t)1239,1,0666|IPC_CREAT);
semMutexAll = semget((key_t)1230,1,0666|IPC_CREAT);
set_semvalue(semBuff,BUFFSIZE);
set_semvalue(semChar,MAXCHR);
set_semvalue(semImage,MAXIMAGE);
set_semvalue(semAudio,MAXAUDIO);
set_semvalue(semVideo,MAXVIDEO);
set_semvalue(semMutexCpu,1);
set_semvalue(semMutexAll,1);
Here is shared memory
key_t ShmKEY;
key_t ShmQ;
int ShmContID;
int ShmQID;
int status;
queue *buffArea;
buffArea = (queue*)malloc(sizeof(queue));
initQueue(buffArea);
control * params;
params = (control*)malloc(sizeof(control));
ShmKEY = ftok("./", 'A');
ShmQ = ftok("./", 'B');
if((ShmContID = shmget(ShmKEY,sizeof(params),IPC_CREAT | 0666)) == -1)
{
//Gets shared memory Id --> IPC_PRIVATE key
perror("shmget");
exit(1);
}
if((ShmQID = shmget(ShmQ,sizeof(buffArea),IPC_CREAT | 0666)) == -1)
{
//Gets shared memory Id --> IPC_PRIVATE key
perror("shmget");
exit(1);
}
Here is semaphore header
#ifndef SHAREDSMPH_H_
#define SHAREDSMPH_H_
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
static int semBuff;
static int semChar;
static int semImage;
static int semAudio;
static int semVideo;
static int semMutexCpu;
static int semMutexAll;
static int set_semvalue(int sem_id,int val)
{
union semun sem_union;
sem_union.val=val;
if(semctl(sem_id,0,SETVAL,sem_union) == -1)
{
fprintf(stderr, "Failed to semvalue\n");
return(0);
}
return (1);
}
static void del_semvalue(int sem_id)
{
union semun sem_union;
if(semctl(sem_id,0,IPC_RMID,sem_union) == -1)
fprintf(stderr, "Failed to delete semaphore\n");
}
static int get_semvalue(int sem_id)
{
union semun sem_union;
int value = semctl(sem_id,0,GETVAL,sem_union);
//printf("semvalue:%d\n",value);
return value;
}
static int semaphore_p(int sem_id)
{
struct sembuf sem_b;
sem_b.sem_num=0;
sem_b.sem_op=-1; /* P */
sem_b.sem_flg=SEM_UNDO;
if(semop(sem_id,&sem_b,1) == -1)
{
printf("semaphore_p failed\n");
return (0);
}
return (1);
}
static int semaphore_v(int sem_id)
{
struct sembuf sem_b;
sem_b.sem_num=0;
sem_b.sem_op=1; /* V */
sem_b.sem_flg=SEM_UNDO;
if(semop(sem_id,&sem_b,1) == -1)
{
printf("semaphore_v failed\n");
return (0);
}
return (1);
}
#endif
Something wrong in this code? especially semaphores , problem is semaphore values are always initialized in different processes.. When i call semaphore_v and semaphore_p functions in processes they works accurate but for example semBuff semaphore is always initialized to 1024 always.

Resources