This program is suppose to create a shared memory between a child and parent process where the child process saves into it the fibonacci sequence of a certain length (argument) and the parent process spits it out. it's also suppose to attach and detach the shared memory. Everything seems functional except for the fact that I get this error:
proj2.cpp:40: error: no match for 'operator*' in 'shared_data *shm' error
Any help? code below.
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <iostream>
#define MAX_SEQUENCE 10
struct shared_data{
long fib_sequence[MAX_SEQUENCE];
int sequence_size;
} shared_data;
using namespace std;
char * shm;
int Fibonacci(int n){
int first = 0, second = 1, temp = 0;
shared_data.fib_sequence[0] = first;
shared_data.fib_sequence[1] = second;
for(int i = 2; i<=n; i++){
temp = first + second;
shared_data.fib_sequence[i] = temp;
first = second;
second = temp;
}
return 0;
}
int main(int argc, char *argv[])
{
pid_t pid;
int seg_id;
const int shd = 4096;
seg_id = shmget(IPC_PRIVATE, shd, S_IRUSR | S_IWUSR);
shared_data *shm = shmat(seg_id, NULL, 0);
int number = atoi(argv[1]);
if(number < 0 || number > 10){
cout << "Invalid number. Please enter a number greater than 0 \n";
return(1);
}
shared_data.sequence_size = number;
pid = fork();
if(pid == 0)
Fibonacci(number);
else{
waitpid(pid,0,0);
for (int i = 0; i <= shared_data.sequence_size; i++)
cout << shared_data.fib_sequence[i];
cout << "\n";
}
return 0;
}
You defined a struct shared_data and at the same time created an object of type shared_data with the name .... shared_data.
Then you create a char* called shm.
So in shared_data *shm = shmat(seg_id, NULL, 0);, the * is interpreted as the binary * operator, trying to 'multiply' your object shared_data with your char pointer shm.
This line:
shared_data *shm = shmat(seg_id, NULL, 0);
has the following properties:
shared_data is an object, not a type.
shm is an object that was declared earlier as well.
You are attempting to multiply those two variables together, and then assign to the result.
You might want something like:
struct shared_data *shm = shmat(seg_id, NULL, 0);
Or you might want to use a typedef in your declaration of the shared_data struct.
Related
I wrote a c++ code to multithreaded copying a file to another directory in linux. but doesn't work(just it made an empty file in directory).
I don't know what's the problem? I think my tread has no right access to write in the shared file. but don't know what should I do.
It should work when typed in terminal :
$./a.out <file name> <dir> <thread number (default 4)>
This is my code:
/*Multithreads file copier*/
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <sys/sendfile.h>
#include <unistd.h>
#include <cstdio>
char* file;
char* fileout_path;
int fin, fout;
// part of each thread
struct PART{
off_t* offset =0;
size_t size;
};
//multithreading
void *Copy (void * data)
{
struct PART *mypart;
mypart = (struct PART *) data;
//open file to read and write
fin = open(file, O_RDONLY,0);
fout = open(fileout_path, O_WRONLY|O_CREAT, 0644);
unsigned long a = static_cast<unsigned long>(mypart->size);
lseek(fout, a, SEEK_SET); //set offset by size of the part
//use sendfile instead read and write to easier code
sendfile(fin, fout, mypart->offset, mypart->size);
printf("threading....\n");//to know the thread ran
pthread_exit(0);
}
int main(int argc, char *argv[])
{
int threads_number;
if (argv[3]!= NULL)
{
threads_number = atoi(argv[3]);
}
else
{
threads_number = 4;//default thread number
}
//multithreading datatypes
pthread_t tid[threads_number];
pthread_attr_t attr;
pthread_attr_init(&attr);
struct stat f_stat;
struct PART part[threads_number];
//allocation size of each part
unsigned long part_size = f_stat.st_size / threads_number;
for(int i =0; i <number_threads; i++)
{
if ( i == threads_number -1)
{
part[threads_number].size = f_stat.st_size - (part_size * (threads_number -1));
}
else
{
part[i].size = part_size;
}
}
file = argv[1];
stat(file, &f_stat);
fileout_path = argv[2];
int fin1 = open(file, O_RDONLY,0);
int fout1 = open(fileout_path, O_WRONLY|O_CREAT, 0644);
for (int j = 0; j < threads_number; j++)
{
pthread_create(&tid[j], NULL, Copy, (void *)&part[j]);
pthread_join(tid[j],NULL);
}
printf("thread is done.\n");
close(fout);
close(fin);
return 0;
}
I am having a bit of trouble getting a System V Message Queue setup and working properly on Linux. The idea is to get a central node to pull data from several other nodes. The trouble is that the central node ends up sitting there waiting for the other nodes to send messages. I have looked at the values for the mailboxes and they are the same across all processes. I.E. 0 for the central mailbox, 32769 for other process 1, ect. I have no idea on why it appears to fail. I have tried to change the priority parameter in msgrcv to 0 to accept all incoming messages and the same issue occurs. Any help would be much appriciated. (Sorry for the lack of comments.)
Here is the code for the central node:
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <iostream>
struct{
long priority;
int temperature;
int pid;
int stable;
} msgp;
const int mainMailID = 8484;
using namespace std;
int main(int argc, char* argv[]){
//declare needed variables
int centralMailID;
int externalMailID[4];
int tempdata;
int externalTempature[4];
int externalTemperatureLast[4];
//set initial values for msgp
msgp.priority = 2;
msgp.temperature = atoi(argv[1]);
msgp.pid = 0;
msgp.stable = 0;
//create the central mailbox
centralMailID = msgget(mainMailID, 0600 | IPC_CREAT);
if(centralMailID == -1){
cout << "Message Queue Creation Failed" << endl;
}
else{
cout << "Message Queue Created" << endl;
}
//create the external mailboxes
for(int i = 0; i < 4 ; i++){
externalMailID[i] = msgget(mainMailID + i+1, 0600 | IPC_CREAT);
if(externalMailID[i] == -1){
cout << "Message Queue " << i << " Creation Failed" << endl;
}
else{
cout << "Message Queue " << i << " Created" << endl;
}
}
printf("%i", externalMailID[0]);
while(msgp.stable == 0){
int centralTemperature = msgp.temperature;
//get the tempatures from the external sensors.
for(int i = 0; i<4; i++){
tempdata = msgrcv(externalMailID[i], &msgp, sizeof(msgp)-sizeof(long), 2, 0);
cout << "Recived data from sensor " << msgp.pid << endl;
externalTempature[i] = msgp.temperature;
}
if(externalTempature[0] == externalTempature[1] == externalTempature[2] == externalTempature[3] == centralTemperature){
msgp.stable = 1;
continue; //could also use break
}
int sum = 0;
for(int i = 0; i<4; i++){
sum = sum + externalTempature[i];
}
centralTemperature = ((2 * centralTemperature) + sum)/6;
msgp.temperature = centralTemperature;
for(int i = 0; i<4; i++){
tempdata = msgsnd(externalMailID[i], &msgp, sizeof(msgp)-sizeof(long), 0);
printf("Sent data to external mailbox %i", i);
}
}
printf("Process ended");
return 0;
}
Here is the code for the other nodes:
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <iostream>
struct{
long priority;
int temperature;
int pid;
int stable;
} msgp;
const int mainMailID = 8484;
using namespace std;
int main(int argc, char* argv[]){
int centralMailID = msgget(mainMailID, 0600 | IPC_CREAT);
int pid = atoi(argv[2]);
int externalMailID = msgget(mainMailID + pid, 0600 | IPC_CREAT);
int externalTemperature = atoi(argv[1]);
int tempdata;
cout << externalMailID << endl;
msgp.priority = 2;
msgp.pid = pid;
msgp.stable = 0;
while(msgp.stable == 0){
msgp.temperature = externalTemperature;
tempdata = msgsnd(centralMailID, &msgp, sizeof(msgp)-sizeof(long), 0);
tempdata = msgrcv(externalMailID, &msgp, sizeof(msgp)-sizeof(long), 2, 0);
externalTemperature = ((externalTemperature * 3) + (msgp.temperature * 2))/5;
if(msgp.stable == 1){
continue;
}
}
printf("Child Process Ended");
return 0;
}
You're using the system V api, which is probably not what you want. See here for more details:
http://mij.oltrelinux.com/devel/unixprg/#ipc__posix_msgqs
The msgget, msgctl, msgsnd, msgrcv commands are part of the older, system V api, and while the semantics are similar, are not posix queues. A couple of quick google search for system V queue tutorials/examples are likely to solve your problem.
If you're genuinely looking to use posix queues, switch to and look for documentation on the mq_open, mq_close, mq_unlink, mq_send, mq_receive, mq_getattr, mq_setattr api.
I have written two program (program 1 and program 2) to communicate with each other using shared memory. program 1 reads from a file a sentence and pass it after modification to get first letter of each word and its size to the next program ( program 2) . I faced race condition problem. I added Peterson algorithm but once I execute the 2 programs one in foreground and one in background I didn't get any result.
-once i remove the Peterson algorithm my programs work
-i'm working in linux using c++
program 1
#include<iostream>
#include<fstream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
int filesize(){
ifstream input;
input.open("file1.txt");
string temp;
int i = 0;
while(input>>temp){i++;}
input.close();
return i;
}
struct shdata
{
char c;
int n;
int size;
bool flag[2];
int turn;
};
int main(){
ifstream input;
input.open("file1.txt");
int shmid;
key_t key = 8006;
struct shdata *shm;
shmid = shmget(key, sizeof(struct shdata), IPC_CREAT | 0666);
if(shmid < 0){
cout<<"Error .. Can not get memory\n";
exit(0);
}
shm = (struct shdata *)shmat (shmid, NULL, 0);
if(shm <= (struct shdata *)(0))
{
cout<<"Errors.. Can not attach\n";
exit(1);
}
shm->flag[0]=false;
shm->flag[1]=true;
string temp;
while(input>>temp){
shm->flag[0]=true;
shm->turn = 1;
while(shm->flag[1]== true && shm-> turn == 1 );
shm->c=temp[0];
shm->n=temp.size();
shm->size = filesize();
shm->flag[0]=false;
sleep(1);
}
return 0;
}
program 2
#include<iostream>
#include<fstream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
int filesize(){
ifstream input;
input.open("file1.txt");
string temp;
int i = 0;
while(input>>temp){i++;}
input.close();
return i;
}
struct shdata
{
char c;
int n;
int size;
bool flag[2];
int turn;
};
int main(){
int shmid;
key_t key = 8006;
struct shdata *shm;
shmid = shmget(key, sizeof(struct shdata), 0);
if(shmid < 0)
{
cout<<"Error .. Can not get memory\n";
exit(0);
}
shm = (struct shdata *)shmat (shmid,0, 0);
if(shm <= (struct shdata *)(0))
{
cout<<"Error .. Can not attach\n";
exit(1);
}
int c =0;
while(c<shm->size){
shm->flag[1] = true;
shm->turn=0;
while( shm->flag[0]==false && shm->turn == 0);
sleep(1);
for(int i = 0; i < shm->n ;i++)
{
cout<<shm->c;
}
cout<<endl;
shm->flag[1]=false;
c++;
}
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
program 2 never gets into the while(c<shm->size) loop because at that point shm->size is 0. To get around it, progran 1 should initialize shm->size before program 2 reaches that point. This might lead to another race condition because there doesn't seem to be any mechanism to ensure that the shared memory is initialized by program 1 before program 2 starts using it.
It seems to work without the Peterson algorithm because in that case program 1 doesn't wait on the flag and initializes shm->size further down in the loop.
You are using the flag member to synchronize you 2 programs but this cant work because you cant suppose the sequence of read/writes. You must use a small dialect in order to make your two programs starts in the correct order.
I am writing this code, which basically takes an argument specifying how many child threads I want, forks to get them, and then prints all the pids which are stored in an array.
This would be fine if only the parent would need the PIDs, but I also need the child to get their IDS (pcid). I copy and pasted some code from the net (which I didn't really understand), so I'm not sure why it's not working.
I get a segmentation error after the first PID prints.
What's wrong here?
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/shm.h>
#include <sys/ipc.h>
int main(int argc, char *argv[])
{
if(argc < 2) {
printf("ERROR: No arguments fed.\n");
exit(-1);
}
int amount = atoi(argv[1]);
int i;
int pid = 1;
int pcid = 0;
key_t key;
int shmid;
int *arr[amount];
key = ftok("thread1.c",'R');
shmid = shmget(key, 1024, 0644 | IPC_CREAT);
for(i = 0; i < amount; i++)
{
if(pid != 0)
{
pid = fork();
}
*arr = shmat(shmid, (void *) 0, 0);
if(pid != 0)
{
*arr[i] = pid;
}
else
{
pcid = *arr[i];
break;
}
}
if(pid != 0)
{
printf("Printing PID Array:\n");
for(i =0; i < amount; i++)
{
printf("%d\n", *arr[i]);
}
}
else
{
printf("My PID: %d\n",pcid);
}
}
you are using an array of pointers. And in line *arr = shmat(shmid, (void *) 0, 0) you assigned the shared memory access point to the first element of array. Now when you are using *arr[i] = pid it will go to the array i+1 element where an unknown address stays and you try to put a value there. so you got segmentation fault.
I've written a program that uses a vector and a map.
When i run it, i get this following error message:
lru: malloc.c:3552: munmap_chunk: Assertion `ret == 0' failed.
Abort
What is the meaning of this error message?
P.S.
When i run my program with valgrind - it passes, with no 'abort'.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <map>
#include "byutr.h"
using namespace std;
///////////////////////////////////////////
/* DEFINE ZONE */
///////////////////////////////////////////
#define NUM_OF_ARGS 4
#define NUM_OF_DIFF_PAGES 100000
///////////////////////////////////////////
/* GLOBAL VARIABLES */
///////////////////////////////////////////
p2AddrTr tr;//a pre-defined struct
vector<uint32_t> stack;
vector<int> depths;
map<uint32_t, int> pages;
map<uint32_t, int>::iterator it;
int main(int argc, char **argv)
{
stack.reserve(NUM_OF_DIFF_PAGES);
FILE *ifp;//TODO remove!
// unsigned long i;//TODO int OR unsigned long??
int i;
unsigned long pCnt =0;
if(argc != NUM_OF_ARGS)
{
fprintf(stderr,"usage: lru <pageSize> <startAt> <numAccesses>\n");
exit(1);
}
int pageSize = atoi(argv[1]);
int startAt = atoi(argv[2]);
int numAccesses = atoi(argv[3]);
int k;
//Skip some entries if needed
for(k=0;k< startAt;k++){
fread(&tr, sizeof(p2AddrTr), 1, stdin);
}
//size_t bytes = fread(&tr, sizeof(p2AddrTr),1, stdin);
//fread(&tr, sizeof(p2AddrTr),1, stdin); TODO here??
i = 0;
while((!feof(stdin)) && (i<numAccesses)){
fread(&tr, sizeof(p2AddrTr),1, stdin);
//prints the address of the memory access
printf("%08lx ", tr.addr);
cout<<endl;
int currAddr = (tr.addr)/pageSize;
if(pages.find(currAddr) == pages.end()){//New page
pCnt++;
//insert the new page to the map
pages.insert(pair<uint32_t, int>(currAddr,pCnt));
//insert the new page to the 'stack'
stack.push_back(currAddr);
}
else{//page already exists
size_t j;
//find the page in the stack
for(j=0;j<stack.size();j++){
if(stack[j] == currAddr){
cout << "passed stack[j]"<<endl;
depths.push_back(stack.size() - j);
break;
}
}
//move the page to the top of the stack
stack.erase(stack.begin() + (j-1));
stack.push_back(currAddr);
}
i++;
}
return (0);
}
I see at least one error:
stack.erase(stack.begin() + (j-1));
If j is 0, this tries to erase an element before the beginning of the list, resulting in a crash.