I started a week ago understanding and working with semaphores and shared memory, and actually created this program, the problem is i cant find anything wrong with it i been looking at it for hours and everything seems correct.. The code compiles and i can create the build but when i execute it nothing happens ...
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <semaphore.h>
#define MAXCHILDS 4
#define MAX_SIZE 10
#define MAX_WRITES 4
typedef struct{
int m[MAX_SIZE][MAX_SIZE];
} matrix;
/*fork variables*/
pid_t child[MAXCHILDS];
/*semphores variables */
sem_t *empty, *full, * mutex;
/*share memory id*/
int shmid;
/*shared memory array pointer */
matrix * sh_mem;
/*pointer to matrix*/
int **p;
void init(){
/*create pointer to matrix*/
p = &sh_mem->m;
/*semaphores unlink and creation */
sem_unlink("EMPTY");
empty=sem_open("EMPTY",O_CREAT|O_EXCL,0700,MAX_WRITES);
sem_unlink("FULL");
full=sem_open("FULL",O_CREAT|O_EXCL,0700,0);
sem_unlink("MUTEX");
mutex=sem_open("MUTEX",O_CREAT|O_EXCL,0700,1);
/*initialize shared memory */
shmid = shmget(IPC_PRIVATE,sizeof(matrix),IPC_CREAT|0777);
/*map shared memory*/
sh_mem = (matrix*)shmat(shmid,NULL,0);
if(sh_mem== (matrix*)(-1)){
perror("shmat");
}
}
void writer(int ** m){
int i,k;
for(i = 0;i<MAX_SIZE;i++){
for(k= 0;k<MAX_SIZE;k++){
m[i][k] = 0;
}
}
}
void reader(int **m){
int i = 0;
int k = 0;
for(i = 0;i<MAX_SIZE;i++){
for(k= 0;k<MAX_SIZE;k++){
printf(m[i][k]);
}
printf("\n");
}
}
void terminate() {
sem_close(empty);
sem_close(full);
sem_close(mutex);
sem_unlink("EMPTY");
sem_unlink("FULL");
sem_unlink("MUTEX");
shmctl(shmid, IPC_RMID, NULL);
}
int main(int argc, char **argv)
{
int i;
init();
for(i = 0;i<MAXCHILDS;i++){
if((child[i]= fork()) < 0) // error occured
{
perror("Fork Failed");
exit(1);
}
if((child[i] =fork())==0){
writer(p);
exit(0);
}
}
/*father*/
reader(p);
wait(NULL);
terminate();
return 0;
}
The childs are supposed to write the the matrix in shared memory, and the father is supposed to read the shared memory array and the print the matrix.
Can you help me with this? Thanks for the help ...
You have several problems with your code.
You declare your p variable as follows:
int **p;
But the actual type of your array is int[MAXSIZE][MAXSIZE]. Although those can both be considered 2-dimensional arrays, they are not at all the same type and do not share the same structure in memory:
int ** is a pointer to a pointer to an integer. When used as a 2-dimensional array, it describes a 2-level array. The first level (dereferencing the pointer once) contains an array of int * pointers that each point to 1-dimensional arrays of integers.
int[MAXSIZE][MAXSIZE] is a flat 2-dimentional array. It is a single pointer to an array of MAXSIZE*MAXSIZE integers. It has the same memory structure as the 1-dimensional array int[MAXSIZE*MAXSIZE] even though it offers the convenience of using 2 levels of subscripts.
Passing around pointers to type[][]-style arrays in C is non-intuitive and very difficult to get right. I don't advise doing it. You might consider passing pointers to your matrix type instead. Still, it is possible to get it to work with this declaration:
typedef int array2d[MAX_SIZE][MAX_SIZE];
array2d *p;
then you have to change the m parameter in reader and writer to array2d *m instead or int **m and use it as *m instead of just m. This gets ugly. Like I said, consider using your matrix type instead.
This problem should have been caught by the compiler. It should have been giving you lots of type mismatch warnings. Make sure you always compile with gcc -Wall and aim to have your program compile with no errors and no warnings.
In init(), you set p too early. You should set it at the end of the function after sh_mem has been assigned, not at the start of the function.
You are fork()ing too many processes in your main() function, as discussed in comments above. You probably meant to call fork() only once each time through the for loop, not twice.
You don't wait until the writers have finished filling out the shared memory structure before you go ahead and read its contents.
Note that even if you move your wait(NULL) before the call to reader(), that's not enough, since wait(NULL) will only wait for one child process to complete, not all of them.
In general, you should compile your program with warnings enabled, pay attention to the warnings, and fix them before wondering what might be wrong with your program. If it still does something unexpected, you should run it under a debugger, use breakpoints, inspect variables, and try to take a look at what's happening. Using these two techniques, you probably would have solved your problem without needing to post here.
Related
I think the print result should be 500, but the result was weird - it said 32728, which is meaningless.
#include<stdio.h>
#include<pthread.h>
void* testFunction(void*);
int main(void)
{
void* result;
pthread_t tid;
pthread_create(&tid, NULL, testFunction, NULL);
pthread_join(tid, &result);
printf("%d\n", *((int*)result));
}
void* testFunction(void* args)
{
int time;
time = 500;
pthread_exit((void*)&time);
}
In this code, this is the flow of what I thought
(void*)result has time's address.
(int*)result has time's address. Because of (int*), the program should know result variable is referring to int-type variable.
*((int*)result) means the value of what result variable refers to, so it would be time's value, which is 500.
Can you let me know what I thought wrong?
The problem is that time no longer exists by the time you come to check it. One way around that is to play with the casting. Instead of
pthread_exit((void*)&time);
use
pthread_exit((void*)time);
Then, when you are extracting the result, use
*((int) result)
Another minimal fix is to make time a static. That way, it is not stored in the stack and always exists.
What's wrong is that time is going out of scope when the thread function exits, meaning that dereferencing its address is undefined behaviour. And you are dereferencing after that, since it happens after the pthread_join() call.
There's a chance that something else will be using that memory (probably on the stack but no mandated, since a stack isn't itself mandated), which would explain the strange value.
But, regardless of what's actually happening, it's not something you're allowed to do in C. Or, more correctly, you can do it, just don't expect sane results.
As others already pointed out, the problem is that the pointer received by pthread_join() points nowhere the moment the function returned. As the memory allocate for int time has already been deallocated, as the function has already ended.
There are two possibilities to have pthread_join() return a pointer to valid memory:
Have the thread function allocate it dynamically.
#include <stdlib.h> /* For malloc() and free(). */
#include <stdio.h>
#include <pthread.h>
void* testFunction(void* pv_unused)
{
int * ptime = malloc(sizeof *ptime);
/* Add error checking/handling here! */
*ptime = 500;
pthread_exit(ptime);
}
int main(void)
{
...
pthread_join(tid, &result);
printf("%d\n", *((int*)result));
free(result); /* Free the memory that has been allocated by the thread-function. */
}
Pass a pointer to valid memory to the thread-function.
#include <stdio.h>
#include <pthread.h>
void* testFunction(void* pv_time)
{
int * ptime = pv_time;
*ptime = 500;
pthread_exit(ptime);
}
int main(void)
{
pthread_t tid;
int time;
pthread_create(&tid, NULL, testFunction, &time);
{
void * pv;
pthread_join(tid, &pv);
if (pv != &time)
{
/* Something went wrong! */
}
}
printf("%d\n", time);
}
Below I have to examples of code that do the same thing and give the same output. In the first, I use pointer to pointer argument passing to eliminate the use of ans as a global. In the second, I madeans a global which eliminated the additional uses of * when dealing with pointer to pointer:
Example 1:
// pointer to pointer
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
unsigned char serial[] = {
0x1,0x2,0x3,0x4
};
void checkSerial(unsigned char* buf, unsigned char ** ans)
{
int i;
unsigned char *part;
part = 0;
i=2;
part = &buf[i];
*ans = (unsigned char*)malloc(2);
memset(*ans,0,2);
memcpy(*ans,part,2);
printf("0x%x\n",**ans);
++(*ans);
printf("0x%x\n",**ans);
}
int main(void)
{
unsigned char *ans, *buf;
while(1)
{
buf = malloc(4);
memset(buf,0,4);
memcpy(buf, serial, sizeof(serial));
checkSerial(buf, &ans);
--ans;
printf("the value is 0x%x\n", *ans);
free(buf);
free(ans);
sleep(3);
}
return 0;
}
Example 2:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
unsigned char serial[] = {
0x1,0x2,0x3,0x4
};
unsigned char ans[2];
void checkSerial(unsigned char* buf)
{
int i;
unsigned char *part;
part = 0;
i=2;
part = &buf[i];
int j;
for(j=0;j<2;j++)
{
ans[j] = part[j];
}
printf("0x%x\n",*ans);
++(*ans);
printf("0x%x\n",*ans);
}
int main(void)
{
unsigned char *buf;
while(1)
{
buf = malloc(4);
memset(buf,0,4);
memcpy(buf, serial, sizeof(serial));
checkSerial(buf);
printf("the value is 0x%x\n", *ans);
free(buf);
sleep(3);
}
return 0;
}
Which technique is preferred in C?
Avoid global variables when it is not necessary. Going with first example is preferable.
Global variables are easily accessible by every functions, they can be read or modified by any part of the program, making it difficult to remember or reason about every possible use.
Keep variables as close to the scope they are being used in as possible. This prevents unexpected values for your variables and potential naming issues.
I personally don't like defining global variable where there is ways to avoid it.
But some guys say that, the concept of pointer is very much confusing. I don't feel that though..
My advice, if you get confuse with pointers try to avoid it with defining global variable. Otherwise, use pointers... :)
TL;DR: Solutions 1 and 2 are both bad.
The way you wrote the example makes malloc useless since you know the size of ans and buf at compile-time, if those are really known at compile-time then , just don't use malloc at all, declare variables on the stack. In C, generally avoid dynamic memory allocation as much as possible and prefer to create buffers which can hold the maximum size a buffer can have in your application. That avoids this kind of problems in the first place. The way you wrote the example makes malloc useless since you know the size of ans and buf at compile-time. The only place where dynamic memory allocation can be useful is for buffers whose sizes are unknown at compile-time, but you can still avoid it (see below). If buf is an incoming message, and ans the answer to this message, the size of ans can be unknown at compile-time, at least if you use variable-length messages.
Your version 2 is not working and can not work! First you declared ans to be an array of size 1 and iterate over it until index 2(now you edited that). Second to declare the array ans as global you would need to know its size at compile-time, and then of course if you knew its size at compile-time you would just declare the array ans in the function checkSerial. Moreover, when you declare a variable which is used by several functions in C don't forget to declare it static, otherwise it can be accessed from all files in your project.
A solution avoiding dynamic allocation, notice you avoid the disadvantages of your 2 solutions: the pointer to pointer and the global variable, and moreover your program can not leak since you don't use dynamic allocation:
enum {MSG_MAX_SIZE = 256 };
typedef struct message {
uint8_t payload[MSG_MAX_SIZE];
size_t msg_size;
} message_t;
void checkSerial(const message_t *buf, message_t *ans)
{
//parse buf and determine size of answer
...
...
//fill answer payload
ans->msg_size = buf[42];
}
int main(void)
{
while (1) {
message_t buf;
getMsg(&buf);
message_t ans;
checkSerial(&buf, &ans);
}
}
Say I want to compute the product of n complex numbers.
What I'm trying to do is that compute the product of the 2*i and 2*i+1 (i=0;i<n/2) complex numbers in threads. ie, clump 2 numbers together and compute their product, therefore I shall get n/2 products. Then again perform the same action on these n/2 products. So on and so forth, and carry on till the value of n is 1.
Here's my code
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
struct complex{
int a;
int b;
};
struct complex arr[1000];
struct arg {
struct complex arr1;
struct complex arr2;
int i;
};
//struct arg *argv;
struct arg *argv=malloc(sizeof(struct arg));
void *multiplier(struct arg *argv)
{
int real,imaginary;
real=(argv->arr1.a)*(argv->arr2.a)-(argv->arr1.b)*(argv->arr2.b);
imaginary=(argv->arr1.a)*(argv->arr2.b)+(argv->arr1.b)*(argv->arr2.a);
arr[argv->i].a=real;
arr[argv->i].b=imaginary;
printf("real=%d imaginary=%d no=%d\n",real,imaginary,argv->i);
pthread_exit(0);
}
int main(void)
{
int n,i,j,flag=0,q;
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d + i%d",&arr[i].a,&arr[i].b);
for(i=0;i<n;i++)
printf("%d + i%d\n",arr[i].a,arr[i].b);
while(n!=0)
{
if(n%2==1)
flag=1;
else
flag=0;
for(i=0;i<n/2;i++)
{
argv->arr1.a=arr[2*i].a; /* SEG FAULT HERE */
argv->arr1.a=arr[2*i].b;
argv->arr2.a=arr[2*i+1].a;
argv->arr2.a=arr[2*i+1].b;
argv->i=i;
pthread_create(&tid,&attr,multiplier,(void *) argv);
}
pthread_join(tid,NULL);
if(flag==1)
{
arr[n/2].a=arr[n-1].a;
arr[n/2].b=arr[n-1].b;
}
n=n/2;
}
return(0);
}
However my code gives me seg fault at line 45. I've been trying to figure out what's wrong with it but to no avail. I probably might be making a fundamentally horrendous error, but do help me out.
EDIT 1:
Probably the most stupid error ever.
I can't allocate memory globally like the way I just did.
I just inserted the Malloc into the main function and the program works.
Each thread needs it's own memory passed in via argv to not overwrite the other thread data.
So you might liek to move this line
struct arg * argv = malloc(sizeof(struct arg));
to here:
for(i = 0; i < n/2; ++i)
{
struct arg * argv = malloc(sizeof(*argv));
argv->arr1.a = arr[2*i].a;
Also checking the result of the calls malloc() might not be a bad idea.
Then let the thread function free() its memory when its done with it:
void * multiplier(struct arg * argv)
{
...
free(argv);
pthread_exit(0);
}
Also the thread function to be passed to pthread_create()is defined as:
void *(*)(void *)
So you shall declare yours this way:
void * multiplier(void * pvargv)
{
struct arg * argv = pvargv;
...
It's pretty hard to figure out which of your lines is line 45.
Also, this looks very wrong:
struct arg *argv=malloc(5*sizeof(struct complex));
It's very rarely correct to mis-match types like that, and struct complex looks nothing like struct arg, so this really seems strange. Also, you shouldn't have a global named argv while u
First, I'm not sure if the memory size you allocate for argv is sane enough. Second, you modify this argv thing, create a thread and immediately overwrite it, probably, before the thread even gets its hands on it.
this program is written in C
it supposed to get a two D array( matrixAdd) and scan it with scanMtx (the scanning function isn't here becuase the code isn't relevant)
the problem: the EDMtx function return the scanning matrix 1,1,1,,1,-8,1,,1,1,1
when it return back to main it is : 0,0,0,0,0,0,junk,junk,junk
it seems that there is a address error
what did i do wrong?
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
struct matrix
{
int* ptr;
int row;
int column;
};
matrix EDMtx();
void main( int argc, char* argv[])
{
int matrixAdd[5][5]={{1,1,1,3,4},{1,1,1,3,4},{1,1,1,3,4},{1,1,1,3,4},{1,1,1,3,4}};
matrix mtx;
matrix scanMtx;
mtx.ptr=&matrixAdd[0][0];
mtx.row=5;
mtx.column=5;
scanMtx= EDMtx();
// mtx= ScanM(mtx,1,1,scanMtx);- doesn't important to you.
getchar();
}
matrix EDMtx()
{
int matrx[3][3]={{1,1,1},{1,-8,1},{1,1,1}};
matrix Mtx;
Mtx.ptr=&matrx[0][0];
Mtx.row=3;
Mtx.column=3;
return Mtx;
}
The variables matrixAdd and matrx, and the memory they point to, have local scope only. If you want them to persist after returning from a function, either declare them static, or redesign your code logic. (e.g. by using malloc to allocate memory explicitly)
In EDMtx, Mtx.ptr is pointed to a stack variable. This is getting destroyed probably. If you want to exchange pointers to variables they must be on the heap
matrix EDMtx()
{
int matrx[3][3]={{1,1,1},{1,-8,1},{1,1,1}};
matrix Mtx;
Mtx.ptr=&matrx[0][0];
Mtx.row=3;
Mtx.column=3;
return Mtx;
}
matrx is a local variable. So, it goes out of scope when upon return of EDMtx(). And the Mtx.ptr has the reference of the local variable matrx. And so the pointer member of scnMtx, is getting garbage values upon dereferencing. Never return references of a local variable.
I have created a function for a thread, but I want to pass multiple parameters to the function.
Here's my source code :
#include "work.h"
#include <stdio.h>
#include <unistd.h>
#include <pthread.h> // compile with -lpthread
int count = 20;
void* ChildProc(void* arg)
{
int i;
for(i = 1; i <= count; i++)
{
printf("%s:%d from thread <%x>\n", arg, i, pthread_self());
DoWork(i);
}
return NULL;
}
void ParentProc(void)
{
int i;
for(i = count / 2; i > 0; i--)
{
printf("Parent:%d from thread <%x>\n", i, pthread_self());
DoWork(i);
}
}
int main(void)
{
pthread_t child;
pthread_create(&child, NULL, ChildProc, "Child");
ParentProc();
pthread_join(child, NULL); // make child a non-daemon(foreground) thread
}
Now how do I pass multiple parameter to ChildProc() method?
One way is either pass an array or a structure. But what if I want to pass multiple variables without an array or a structure?
A fast and junk answer is to create a struct to hold all parameter and pass its pointer
One way is either pass a array or a structure.
That's the way. Pointer to a structure, that is.
what if I want to pass multiple variables withous a array or a structure?
Then you're out of luck. Array or a pointer to a structure is what you need.
You can pass a void * buffer stream and if you know the lengths then you can access them. Its similar to implementation of GArrays.
How do you create them?
void *buffer = malloc(sizeofelements);
memcpy(buffer,element1,sizeof element1);
memcpy(buffer+sizeof element1,element2, sizeof element2);
NOTE: The above is not a compilable C code. You need to work on it.
You can use something of the above sort.
You can later access the variables as you already know the size