Simple question about pointer in c programming - c

I was writing a simple shared memory test program like below.
And I used a line like below.
e_intf[i % 8].flag = i;
I thought it should be like below.
e_intf[i % 8]->flag = i;
But if I use "->" operator, I have errors.
This is a full source code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#define SHM_KEY 0x9998
typedef struct _ethernet_interface {
char name[8];
int32_t flag;
} Ethernet_Interface_t;
int32_t memory_update(void)
{
int32_t i = 0;
int32_t shmid;
Ethernet_Interface_t *e_intf;
int32_t ret;
shmid = shmget(SHM_KEY, 8 * sizeof(Ethernet_Interface_t), 0644|IPC_CREAT);
if (shmid == -1)
{
perror("Shared Memory");
return -1;
}
e_intf = shmat(shmid, NULL, 0);
if (e_intf == (void *)-1)
{
perror("Shared Memory Attach");
return -1;
}
while (1)
{
e_intf[i % 8].flag = i;
if (i < 8)
{
sprintf(e_intf[i % 8].name, "%s%d", "eth", (i % 8));
}
printf("memory_update : e_intf[%d].name = %s, e_intf[%d] = %d\n", i % 8, e_intf[i % 8].name, (i % 8), i);
sleep(2);
i++;
}
ret = shmdt(e_intf);
if (ret == -1)
{
perror("shmdt");
return -1;
}
return 0;
}
int32_t memory_read(void)
{
int32_t i;
int32_t shmid;
Ethernet_Interface_t *e_intf;
int32_t ret;
shmid = shmget(SHM_KEY, 8 * sizeof(Ethernet_Interface_t), 0644|IPC_CREAT);
if (shmid == -1)
{
perror("Shared Memory");
return -1;
}
e_intf = shmat(shmid, NULL, 0);
if (e_intf == (void *)-1)
{
perror("Shared Memory Attach");
return -1;
}
i = 0;
while (1)
{
printf("[%d]memory_read : index = %d\n", i, (i % 8));
printf("[%d]memory_read : e_intf[%d].name = %s\n", i, (i % 8), e_intf[i % 8].name);
printf("[%d]memory_read : e_intf[%d].flag = %d\n", i, (i % 8), e_intf[i % 8].flag);
if (e_intf[i % 8].flag == 42)
{
printf("[%d]memory_read : Exiting\n", i);
break;
}
sleep(1);
i++;
}
ret = shmdt(e_intf);
if (ret == -1)
{
perror("shmdt");
return -1;
}
ret = shmctl(shmid, IPC_RMID, 0);
if (ret == -1)
{
perror("shmctl");
return -1;
}
return 0;
}
int32_t main(int32_t argc, char *argv[])
{
pid_t pid;
pid = fork();
if (pid == 0)
{
/* child process */
memory_update();
}
else
{
/* parent process */
memory_read();
}
exit(0);
}
But when I made another simple test program for pointer operation.
I can use "->" operator as I expected.
Here is the source code for the test program for pointer operation.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct _ethernet_interface {
char name[8];
int32_t flag;
} Ethernet_Interface_t;
int32_t main(int32_t argc, char *argv[])
{
Ethernet_Interface_t intf;
Ethernet_Interface_t *p_intf;
p_intf = malloc(sizeof(Ethernet_Interface_t));
intf.flag = 1111;
p_intf->flag = 2222;
printf("intf.flag = %d\n", intf.flag);
printf("p_intf->flag = %d\n", p_intf->flag);
return 0;
}
Can someone point out why I am confused with these 2 cases?

The answer is very simple - index dereferences the pointer:
pointer[n] === *(pointer + n)
so in your case:
e_intf[i % 8] === *(e_intf + i % 8)
and
e_intf[i % 8].flag == (*(e_intf + i % 8)).flag
if you want to use the -> operator you need pointer, not referenced object.
(&e_intf[i % 8]) -> flag
or
(e_intf + i % 8) -> flag

Related

Trouble with shared memory program in C

I have an assignment that consists of making a program with shared memory that has a parent process, which reads from a .txt and adds its contents to a buffer (this is the shared memory), and two child processes that switch the case of the contents of the buffer, and output them in two files. One child outputs them in uppercase and the other one in lowercase. I've implemented semaphores and shared memory, but my output files turn out empty. By the way, the program is run on Linux; I use a virtual machine for the deed. I'd like to get some guidance as to what I'm not doing correctly.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
int main() {
FILE *archivo, *salida1, *salida2;
int i = 0;
int j, k;
char actual;
key_t claveMC = ftok("UCAB.txt", 5);
int shmid = shmget(claveMC, 512, 0777 | IPC_CREAT);
char *buffer = (char*)shmat(shmid, NULL, 0);
key_t claveSem = ftok("UCAB.txt", 7);
int idsem = semget(claveSem, 1, IPC_CREAT | 0100);
struct sembuf valores;
valores.sem_num = 0;
valores.sem_flg = 0;
semctl(idsem, 0, SETVAL, 1);
archivo = fopen("UCAB.txt", "r");
int id = fork();
int id2;
if (id > 0) {
printf("P: %d", id);
id2 = fork();
if (id2 > 0) {
while (((actual = getc(archivo)) != EOF) && (i < 512)) {
valores.sem_op = -1;
semop(idsem, &valores, 1);
buffer[i] = actual;
valores.sem_op = 1;
semop(idsem, &valores, 1);
i++;
}
valores.sem_op = -1;
semop(idsem, &valores, 1);
printf("%s", buffer);
valores.sem_op = 1;
semop(idsem, &valores, 1);
fclose(archivo);
printf("\nPadre con id: %d", id2);
}
else {
printf("H2: %d", id);
salida2 = fopen("minusculas.txt", "w");
for (j = 0; j < i; j++) {
valores.sem_op = -1;
semop(idsem, &valores, 1);
putc(tolower(buffer[j]), salida2);
valores.sem_op = 1;
semop(idsem, &valores, 1);
}
printf("\nHijo 2 con id: %d", id2);
fclose(salida2);
}
}
else {
//hijo1
printf("H1: %d", id);
salida1 = fopen("MAYUSCULAS.txt", "w");
for (k = 0; k < i; k++) {
valores.sem_op = -1;
semop(idsem, &valores, 1);
putc(toupper(buffer[k]), salida1);
valores.sem_op = 1;
semop(idsem, &valores, 1);
}
printf("\nHijo 1 con id: %d", id);
fclose(salida1);
}
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
The children write i characters to their file, but i is only incremented in the parent after the children have been forked, so their i remains zero.
After fork, the child is a clone of the parent (with differences, like pid). But the address spaces of the parent and child are different. So, the variable "i" of the parent is not the same as the variable "i" of either of the children.

Question about sharing mmapped area between 2 different processes

I'm trying to share mmapped area in 2 processes.
In my program, I create memory_update() process and memory_read() process.
This memory_update() process update mmapped area and tried to read that area in memory_read() process.
But I got when I tried to read the mmapped area.
So far, I don't have good luck to find a solution for this problem.
If you have any idea, please leave your comments.
Here is the source code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/wait.h>
#define COLUMN 80
#define ROW 10
#define BUFSIZE 80
#define SHM_KEY 0x9998
struct _row {
int32_t flag;
unsigned char *buffer;
};
typedef enum {
DATA_READY,
DATA_RESET
} msg_type_t;
struct _ipc_message {
msg_type_t type;
int32_t value;
};
typedef struct _ipc_message ipc_message_t;
typedef struct _row row_t;
int32_t format_number_string(char *buf, int32_t num)
{
sprintf(buf, "%02d", num);
return 0;
}
int32_t update_row(char *buf, char *str)
{
strncpy(buf, str, 80);
return 0;
}
int32_t print_row(char *buf)
{
printf("print_row buf = %p\n", (void *)buf);
printf("%s\n", buf);
return 0;
}
int32_t memory_update(int32_t sk)
{
row_t *p_row;
ipc_message_t msg;
unsigned char *shared_mem;
unsigned char *ptr;
char rbuf[BUFSIZE];
char nbuf[3];
int32_t shmid;
int32_t i;
int32_t ret;
int32_t fd;
shmid = shmget(SHM_KEY, ROW * sizeof(row_t), 0644 | IPC_CREAT);
if (shmid == -1)
{
perror("Shared Memory Error");
return -1;
}
/* Attach Shared Memory */
shared_mem = shmat(shmid, NULL, 0);
if (shared_mem == (void *)-1)
{
perror("Shared Memory Attach Error");
return -1;
}
fd = open("testfile", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd < 0)
{
perror("File Open Error");
}
ptr = mmap(
NULL,
COLUMN * ROW,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
0);
printf("ptr = %p\n", (void *)ptr);
for (i = 0 ; i < ROW ; i++)
{
format_number_string(nbuf, i);
memset(rbuf, 0x20, BUFSIZE);
sprintf(rbuf, "LINE %s :", nbuf);
rbuf[strlen(rbuf)] = ' ';
rbuf[BUFSIZE-1] = 0x0;
update_row(&ptr[i * COLUMN], rbuf);
}
for (i = 0 ; i < ROW ; i++)
{
p_row = (row_t *)&shared_mem[i * sizeof(row_t)];
p_row->flag = 0x99;
p_row->buffer = &ptr[i * COLUMN];
// print_row(p_row->buffer);
}
msg.type = DATA_READY;
msg.value = 0;
send(sk, (void *)&msg, sizeof(ipc_message_t), 0);
i = 0;
for ( ; i < ROW ; i++)
{
p_row = (row_t *)&shared_mem[i * sizeof(row_t)];
if (p_row->flag == 0x0)
{
printf("row[%d] has processed\n", i);
}
else
{
i--;
sleep(1);
}
}
/* Detach Shared Memory */
ret = shmdt(shared_mem);
if (ret == -1)
{
perror("Shared Memory Detach Error");
return -1;
}
ret = munmap(ptr, COLUMN * ROW);
if (ret != 0)
{
printf("UnMapping Failed\n");
return -1;
}
close(fd);
return 0;
}
int32_t memory_read(int32_t sk)
{
row_t *p_row;
ipc_message_t msg;
unsigned char *shared_mem;
int32_t shmid;
int32_t ret;
int32_t i;
while (1)
{
ret = recv(sk, (void *)&msg, sizeof(ipc_message_t), 0);
if (ret < 0)
{
perror("recv error");
return -1;
}
if (msg.type != DATA_READY)
{
continue;
}
else
{
break;
}
}
shmid = shmget(SHM_KEY, ROW * sizeof(row_t), 0644 | IPC_CREAT);
if (shmid == -1)
{
perror("Shared Memory Error");
return -1;
}
/* Attach Shared Memory */
shared_mem = shmat(shmid, NULL, 0);
if (shared_mem == (void *)-1)
{
perror("Shared Memory Attach Error");
return -1;
}
for (i = 0 ; i < ROW ; i++)
{
p_row = (row_t *)&shared_mem[i * sizeof(row_t)];
printf("memory_read process [%d]\n", i);
print_row(p_row->buffer);
p_row->flag = 0x0;
sleep(1);
}
/* Detach Shared Memory */
ret = shmdt(shared_mem);
if (ret == -1)
{
perror("Shared Memory Detach Error");
return -1;
}
return 0;
}
int32_t main(void)
{
pid_t pid;
int32_t sp[2];
int32_t ret;
static const int32_t ps = 0;
static const int32_t cs = 1;
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sp);
if (ret == -1)
{
perror("socketpair");
return -1;
}
pid = fork();
if (pid == 0)
{
close(sp[ps]);
memory_update(sp[cs]);
}
else
{
close(sp[cs]);
memory_read(sp[ps]);
}
return 0;
}
And this is the output.
$ ./mmm
ptr = 0x7fdc214a8000
memory_read process [0]
print_row buf = 0x7fdc214a8000
Segmentation fault (core dumped)
Modifed code to mmap before forking.
And it is working as expected.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/wait.h>
#define COLUMNS 80
#define ROWS 60
#define BUFSIZE 80
typedef enum {
DATA_PRODUCED,
DATA_CONSUMED
} msg_type_t;
struct _ipc_message {
msg_type_t type;
int32_t value;
};
typedef struct _ipc_message ipc_message_t;
int32_t memory_update(int32_t sk, char *buf)
{
ipc_message_t msg;
int32_t ret;
char *msg2 = "updated buffer";
printf("memory_update : 1.buf = %s\n", buf);
memset(buf, 0, 80);
strncpy(buf, msg2, strlen(msg2));
buf[strlen(msg2)] = 0;
printf("memory_update : 2.buf = %s\n", buf);
printf("memory_update : send message from memory_update process\n");
msg.type = DATA_PRODUCED;
msg.value = 0;
send(sk, (void *)&msg, sizeof(ipc_message_t), 0);
while (1)
{
printf("memory_update : receive message from memory_read process\n");
ret = recv(sk, (void *)&msg, sizeof(ipc_message_t), 0);
if (ret < 0)
{
perror("recv error");
return -1;
}
if (msg.type != DATA_CONSUMED)
{
continue;
}
else
{
break;
}
}
printf("memory_update : 3.buf = %s\n", buf);
return 0;
}
int32_t memory_read(int32_t sk, char *buf)
{
ipc_message_t msg;
int32_t ret;
int32_t i;
char *msg3 = "buffer processed";
printf("memory_read : 1.buf = %s\n", buf);
while (1)
{
printf("memory_read : receive message from memory_update process\n");
ret = recv(sk, (void *)&msg, sizeof(ipc_message_t), 0);
if (ret < 0)
{
perror("recv error");
return -1;
}
if (msg.type != DATA_PRODUCED)
{
continue;
}
else
{
break;
}
}
printf("memory_read : 2.buf = %s\n", buf);
memset(buf, 0, 80);
strncpy(buf, msg3, strlen(msg3));
buf[strlen(msg3)] = 0;
printf("memory_read : 3.buf = %s\n", buf);
printf("memory_read : send message from memory_update process\n");
msg.type = DATA_CONSUMED;
msg.value = 0;
send(sk, (void *)&msg, sizeof(ipc_message_t), 0);
return 0;
}
int32_t main(void)
{
pid_t pid;
int32_t sp[2];
int32_t ret;
int32_t fd;
int32_t i;
char *ptr;
char *msg1 = "initial message";
static const int32_t ps = 0;
static const int32_t cs = 1;
fd = open("80bytes", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd < 0)
{
perror("File Open Error");
}
ptr = mmap(
NULL,
80,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
0);
memset(ptr, 0, 80);
strncpy(ptr, msg1, strlen(msg1));
ptr[strlen(msg1)] = 0;
printf("ptr = %s\n", ptr);
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sp);
if (ret == -1)
{
perror("socketpair");
return -1;
}
pid = fork();
if (pid == 0) /* child process */
{
close(sp[ps]);
memory_update(sp[cs], ptr);
}
else /* parent process */
{
close(sp[cs]);
memory_read(sp[ps], ptr);
ret = munmap(ptr, 80);
if (ret != 0)
{
printf("UnMapping Failed\n");
return -1;
}
close(fd);
}
return 0;
}

Issues with pthread in C

I have a problem with the compiling of my program, when I test something like "./philo -p 3 -e 4" I get the error
philo: tpp.c:62: __pthread_tpp_change_priority: Assertion `new_prio == -1 || (new_prio >= __sched_fifo_min_prio && new_prio <= __sched_fifo_max_prio)' failed.
Aborted
But I don't understand where it does come from, as it's working sometimes, for exemple if I test "./philo -p 2 -e 4" it doesn't crash.
The two .h
#ifndef _PHILO_H_
# define _PHILO_H_
#include <pthread.h>
typedef struct s_philosop
{
pthread_t philosophers;
pthread_mutex_t *chopsticks1;
pthread_mutex_t *chopsticks2;
int nbr_occ;
} t_philosop;
int parse_arg(char **argv, int *philo, int *occ);
int create_threads_mutex(int nbr_philo, int occurences);
void *start_routine(void *arg);
void philosoph_eating_chopsticks(t_philosop *philosop);
#endif /* !_PHILO_H_ */
#ifndef __LIBRICEFEREE_EXTERN__
# define __LIBRICEFEREE_EXTERN__
#include <pthread.h>
int RCFStartup(int ac, char **av);
void RCFCleanup();
int lphilo_eat();
int lphilo_sleep();
int lphilo_think();
int lphilo_take_chopstick(const pthread_mutex_t *mutex_id);
int lphilo_release_chopstick(const pthread_mutex_t *mutex_id);
#endif /* __LIBRICEFEREE_EXTERN__ */
And this is my .c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include "philo.h"
#include "extern.h"
void philosoph_comportement(t_philosop *philosop)
{
int i = 0;
if ((pthread_mutex_lock(philosop->chopsticks1)) == 0)
{
printf("%s\n", "Taking left stick");
lphilo_take_chopstick(philosop->chopsticks1);
i++;
}
if ((pthread_mutex_lock(philosop->chopsticks2)) == 0)
{
printf("%s\n", "Taking right stick");
lphilo_take_chopstick(philosop->chopsticks2);
i++;
}
if (i == 2)
{
printf("%s\n", "Eat");
lphilo_eat();
sleep(1);
printf("%s\n", "Sleep");
pthread_mutex_unlock(philosop->chopsticks1);
pthread_mutex_unlock(philosop->chopsticks2);
lphilo_release_chopstick(philosop->chopsticks1);
lphilo_release_chopstick(philosop->chopsticks2);
lphilo_sleep();
}
}
void *start_routine(void *arg)
{
t_philosop *philosop;
int i;
i = 0;
philosop = (t_philosop *)arg;
while (i != philosop->nbr_occ)
{
philosoph_comportement(philosop);
i++;
}
return (0);
}
int create_threads_mutex(int nbr_philo, int occurences)
{
int i;
t_philosop *philosop;
pthread_mutex_t *chopsticks;
i = -1;
if ((chopsticks = malloc(sizeof(pthread_mutex_t) * nbr_philo)) == NULL)
return (2);
if ((philosop = malloc(sizeof(t_philosop) * nbr_philo)) == NULL)
return (2);
while (++i != nbr_philo)
{
philosop[i].nbr_occ = occurences;
philosop[i].chopsticks1 = &chopsticks[i];
if (i - 1 < 0)
philosop[i].chopsticks2 = &chopsticks[nbr_philo];
else
philosop[i].chopsticks2 = &chopsticks[i - 1];
}
i = -1;
while (++i != nbr_philo)
pthread_create(&philosop[i].philosophers, NULL, start_routine, &philosop[i]);
i = -1;
while (++i != nbr_philo)
{
printf("Philo number : %d\n", i);
pthread_join(philosop[i].philosophers, NULL);
}
return (0);
}
int parse_arg(char **argv, int *philo, int *occ)
{
if (strcmp(argv[1], "-p") == 0 && strcmp(argv[3], "-e") == 0 &&
argv[2] != NULL && argv[4] != NULL)
{
*philo = atoi(argv[2]);
*occ = atoi(argv[4]);
}
else if (strcmp(argv[1], "-e") == 0 && strcmp(argv[3], "-p") == 0 &&
argv[2] != NULL && argv[4] != NULL)
{
*philo = atoi(argv[4]);
*occ = atoi(argv[2]);
}
else
return (2);
return (0);
}
int main(int argc, char **argv)
{
int philo;
int occurences;
philo = 0;
occurences = 0;
if (argc != 5)
return (2);
if ((parse_arg(argv, &philo, &occurences)) == 2)
return (2);
RCFStartup(argc, argv);
if ((create_threads_mutex(philo, occurences)) == 2)
return (2);
RCFCleanup();
return (0);
}
You don't initialize any of your mutexes with pthread_mutex_init.
And assuming lphilo_release_chopstick does nothing but unlock a mutex, this code is wrong as it will try to unlock each mutex twice:
pthread_mutex_unlock(philosop->chopsticks1);
pthread_mutex_unlock(philosop->chopsticks2);
lphilo_release_chopstick(philosop->chopsticks1);
lphilo_release_chopstick(philosop->chopsticks2);

print garbage values from the shared memory

I am currently working on a producer-consumer implementation using C.
First, I create a buffer on the shared memory of a variable length that is given by the user in the consumer process.
Then, in the producer process, I need to access the shared memory and puts new data to the buffer so the consumer can consume.
Below is the consumer code:
#include "common.h"
#include <unistd.h>
int fd;
int errno;
int MY_LEN = 0;
Shared* shared_mem;
char *job[4];
int setup_shared_memory(){
fd = shm_open(MY_SHM, O_CREAT | O_RDWR, 0666);
if(fd == -1){
printf("shm_open() failed\n");
exit(1);
}
ftruncate(fd, sizeof(Shared) + MY_LEN*sizeof(char *));
}
int attach_shared_memory(){
shared_mem = (Shared*) mmap(NULL, sizeof(Shared) + MY_LEN*sizeof(char *), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(shared_mem == MAP_FAILED){
printf("mmap() failed\n");
exit(1);
}
return 0;
}
int init_shared_memory() {
shared_mem->data = 0;
int i;
for(i = 0; i < shared_mem->length; i++)
{
shared_mem->arr[i] = 0;
// shared_mem->arr[i] = (char *)calloc(1, sizeof(char*));
}
sem_init(&(shared_mem->mutex), 1, 1);
}
int init_job(){
int i;
for(i = 0; i < 4; i++)
{
job[i] = (char *)malloc(sizeof(char *));
}
}
int take_a_job(int index){
init_job();
char *ds = strdup(shared_mem->arr[index]);
job[0] = strtok(ds, "-");
int i = 1;
while(i < 4)
{
job[i] = strtok(NULL, "-");
i++;
}
// remove the job from the buffer
shared_mem->arr[index] = NULL;
}
int consume_job(int index){
printf("\nPrinter starts printing the job %s, %s pages from Buffer[%d]. The duration is %s seconds and the source is %s.\n",job[3], job[2], index, job[1], job[0]);
sleep(atoi(job[1])); // sleep for job[1] seconds.
}
int main(int args, char *argv[]) {
setup_shared_memory();
attach_shared_memory();
init_shared_memory();
MY_LEN = atoi(argv[1]); // the first parameter following ./printer = the length of the buffer
shared_mem->length = MY_LEN;
//shared_mem->arr = (int*) &shared_mem->arr;
int index = 1;
*(shared_mem->arr) = "1-10-5-6";
*(shared_mem->arr + 1) = "2-5-2-7";
*(shared_mem->arr + 2) = "3-20-10-8";
*(shared_mem->arr + 3) = "4-7-4-9";
take_a_job(index);
int i;
for(i = 0; i < shared_mem->length; i++){
printf("\n\n%d set %s\n", i, shared_mem->arr[i]);
}
consume_job(index);
printf("\n\nHello second check\n\n");
while (1) {}
return 0;
}
Here is the producer code:
#include "common.h"
int fd;
Shared* shared_mem;
char *job;
int setup_shared_memory(){
fd = shm_open(MY_SHM, O_RDWR, 0666);
if(fd == -1){
printf("shm_open() failed\n");
exit(1);
}
}
int attach_shared_memory(){
shared_mem = (Shared*) mmap(NULL, sizeof(Shared), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(shared_mem == MAP_FAILED){
printf("mmap() failed\n");
exit(1);
}
return 0;
}
int create_a_job(int args, char *argv[]){
int i;
job = (char *)calloc(8, sizeof(char *));
if(args != 5)
return 0; //the parameters are not correctly formatted
else{
for(i = 1; i < args; i++)
{
if(i > 1)
strcat(job, "-");
strcat(job, argv[i]);
}
}
strcat(job, "\0");
printf("\nthe job is %s\n", job);
}
int put_a_job(){
printf("shared_mem->length is %d\n\n", shared_mem->length);
int i;
for(i = 0; i < shared_mem->length; i++)
{
if(*(shared_mem->arr + i) == 0)
{
//shared_mem->arr[i] = (char *)malloc(sizeof(job));
//strcpy(shared_mem->arr[i], job);
*(shared_mem->arr + i) = (char *)job;
printf("\n\nThe index is %d\n", i);
//printf("\n\nthe argument is %s at %d\n", job, i);
return i;
}
}
printf("\n\nThe index is %d\n", i);
}
int main(int args, char *argv[]) {
setup_shared_memory();
attach_shared_memory();
// create a job with the parameters
int result = create_a_job(args, argv);
if(result == 0)
{
printf("Not the right parameters.\n");
printf("Plase enter client ID, job duration, number of pages and job ID.\n");
return 0;
}
int i;
put_a_job();
for (i=0; i < shared_mem->length; i++) {
printf("the argument is %s at %d\n", (char *)(shared_mem->arr + i), i);
}
printf("\n\n");
return 0;
}
The common.h file is
#ifndef _INCLUDE_COMMON_H_
#define _INCLUDE_COMMON_H_
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
// from `man shm_open`
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#include <string.h>
#include <semaphore.h>
#define MY_SHM "/JIT"
typedef struct {
sem_t mutex;
int data;
int length; // the length of the buffer
char *arr[0];
} Shared;
#endif //_INCLUDE_COMMON_H_
I first run ./consumer 10 & to allocate a buffer of length 10 and after, I run ./producer 1 2 3 4 to put the job to the buffer and print the buffer, I got garbage values
Any help would be really appreciated! Thank you!
Instruction
*(shared_mem->arr + i) = (char *)job;
is storing the pointer job into the shared mem, not the pointed value.
Maybe you want to use a strncpy.
You cannot share memory address between processes, because of Linux uses virtual memory. To make the story short an address in a process is not valid for a different process.
Be aware that you have a memory leakage because you never call free() for the allocated job.

sem_init Segmentation fault error

The task was to create simulation of warehouse's work. Producers (in an amount of argv[2]) create random number of "goods" (totally argv[1]), and consumers (in an amount of argv[3]) get random number of these goods. The full code is below.
I got segmentation error and tried to debug it and got the following:
Program received signal SIGSEGV, Segmentation fault.
__new_sem_init (sem=0x37, pshared=0, value=1) at sem_init.c:44
44 sem_init.c: No such file or directory
I think the problem is in address-of operator here
sem_init(&(shared->mutex), 0, 1);
How should I change the code to make it work?
Thanks a lot!
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/mman.h>
#define NBUFF 10
#define MAXNTHREADS 100
#define min( a, b ) ( ( a < b) ? a : b )
int nitems, nproducers, nconsumers;
typedef struct shared_s
{
int buff[NBUFF];
int nput;
int nputval;
int nget;
int ngetval;
sem_t mutex, nempty, nstored;
} sharedtype;
int main(int argc, char **argv)
{
sharedtype * shared;
key_t key;
int shmid, semid;
int i, j, prodcount[MAXNTHREADS], conscount[MAXNTHREADS];
shared = mmap(NULL, sizeof(sharedtype),
PROT_READ | PROT_WRITE, MAP_SHARED, -1, 0);
/* Wrong argv */
if (argc != 4)
{
printf("usage: newconsumer <#items> <#producers> <#consumers>\n");
exit(1);
}
nitems = atoi(argv[1]);
nproducers = min(atoi(argv[2]), MAXNTHREADS);
nconsumers = min(atoi(argv[3]), MAXNTHREADS);
pid_t chpidpr [nproducers];
pid_t chpidcon [nconsumers];
/* initilising semaphores */
sem_init(&(shared->mutex), 0, 1);
sem_init(&(shared->nempty), 0, NBUFF);
sem_init(&(shared->nstored), 0, 0);
for (i = 0; i < nproducers; i++) {
prodcount[i] = 0;
switch (chpidpr[i] = fork())
{
case -1:
printf("fork error");
return 1;
case 0:
for (;;)
{
sem_wait(&shared->nempty);
sem_wait(&shared->mutex);
if (shared->nput >= nitems)
{
sem_post(&(shared->nstored));
sem_post(&(shared->nempty));
sem_post(&(shared->mutex));
return 0;
}
shared->buff[(shared->nput) %NBUFF] = shared->nputval;
(shared->nput)++;
(shared->nputval)++;
sem_post(&(shared->mutex));
sem_post(&(shared->nstored));
prodcount[i] += 1;
}
}
}
for (i = 0; i < nproducers; i++)
{
printf("producer count[%d] = %d\n", i, prodcount[i]);
}
for (i = 0; i < nconsumers; i++) {
conscount[i] = 0;
switch (chpidcon[i] = fork())
{
case -1:
printf("error");
return 1;
case 0:
for (;;)
{
sem_wait(&(shared->nstored));
sem_wait(&(shared->mutex));
if (shared->nget >= nitems)
{
sem_post(&(shared->nstored));
sem_post(&(shared->mutex));
return 0;
}
j = shared->nget % NBUFF;
if (shared->buff[j] != shared->ngetval)
{
printf("error: buff[%d] = %d\n", j, shared->buff[j]);
}
shared->nget++;
shared->ngetval++;
sem_post(&(shared->mutex));
sem_post(&(shared->nempty));
conscount[i] += 1;
}
}
}
for (i = 0; i < nconsumers; i++)
{
printf("consumer count[%d] = %d\n", i, conscount[i]);
}
/* destroying semaphores */
sem_destroy(&(shared->mutex));
sem_destroy(&(shared->nempty));
sem_destroy(&(shared->nstored));
exit(0);
}
It looks like your mmap call has failed and return -1. You aren't checking for this condition.
I did a quick addition, and it looks like mutex is at an offset of 56, or 0x38 from the base of sharedtype. Based on the crash report, sem = 0x37, which would be the address of shared->mutex if shared == -1.
I can't find any documentation on why one would call mmap with fd == -1, but I think this may be the source of the issue, combined with not validating the result.

Resources