I made in C a program in Linux of multiplication of matrices of order 1000 A and B. And now I have to add processes!
And now I have to add 4 processes in the multiplication that will result in array C.
1 process for calculating from 0 to 249;
2 process for calculating from 250 to 499;
3 process for calculating from 500 to 749;
4 process for calculating from 750 to 999;
Multiplication is working correctly;
I do not understand much of processes, and the problem lies in the parts of the processes, I can not do what I need;
Follow the code below:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
int id;
int main(){
int i;
int j;
int row;
int col;
int order;
long T1;
long T2;
float delta;
int process_1;
int process_2;
int process_3;
int process_4;
printf("Enter the order of the square matrices A and B: ");
scanf("%d", &order);
T1 = clock();
printf("\nThe square matrices A and B, are order matrices %d",order);
order = order - 1;
row = order;
col = order;
float A[row+1][col+1];
float B[row+1][col+1];
for(i = 0; i <= row; i++){
for(j = 0; j <= col; j++){
printf("\n\nEnter the value of the array A[%d][%d]: ",i+1,j+1);
scanf("%f", &A[i][j]);
printf("\nEnter the value of the array B[%d][%d]: ",i+1,j+1);
scanf("%f", &B[i][j]);
}
}
printf("\nThe multiplication of matrices A and B:\n\n");
id = shmget(IPC_PRIVATE, 100, 0600);
process_1 = fork();
process_2 = fork();
process_3 = fork();
process_4 = fork();
int *a;
a = shmat(id,0,0);
printf("\n\nprocess 1:\n\n");
if(process_1 == 0){
int P1 = 0;
if(P1 <= 249){
for(i = 0; i <= row; i++) {
for(j = 0; j <= col; j++) {
float C[row+1][col+1];
for(int AUX = 0; AUX <= order; AUX++) {
C[i][j] += A[i][AUX] * B[AUX][j];
}
printf("%.2f ",C[i][j]);
}
printf("\n");
}
}
exit(0);
}
printf("\n\nprocess 2:\n\n");
if(process_2 == 0){
int P2 = 250;
if(P2 >=250 && P2 <= 499){
for(i = 0; i <= row; i++) {
for(j = 0; j <= col; j++) {
float C[row+1][col+1];
for(int AUX = 0; AUX <= order; AUX++) {
C[i][j] += A[i][AUX] * B[AUX][j];
}
printf("%.2f ",C[i][j]);
}
printf("\n");
}
}
exit(0);
}
printf("\n\nprocess 3:\n\n");
if(process_3 == 0){
int P3 = 0;
if(P3 >=500 && P3 <= 749){
for(i = 0; i <= row; i++) {
for(j = 0; j <= col; j++) {
float C[row+1][col+1];
for(int AUX = 0; AUX <= order; AUX++) {
C[i][j] += A[i][AUX] * B[AUX][j];
}
printf("%.2f ",C[i][j]);
}
printf("\n");
}
}
exit(0);
}
printf("\n\nprocess 4:\n\n");
if(process_4 == 0){
int P4 = 0;
if(P4 >=750 && P4 <= 999){
for(i = 0; i <= row; i++) {
for(j = 0; j <= col; j++) {
float C[row+1][col+1];
for(int AUX = 0; AUX <= order; AUX++) {
C[i][j] += A[i][AUX] * B[AUX][j];
}
printf("%.2f ",C[i][j]);
}
printf("\n");
}
}
exit(0);
}
waitpid(process_1, NULL, 0);
waitpid(process_2, NULL, 0);
waitpid(process_3, NULL, 0);
waitpid(process_4, NULL, 0);
T2 = clock();
delta = (float)(T2-T1)/CLOCKS_PER_SEC;
printf("\n\Time %.5f seconds\n\n",delta);
return 0;
}
How can I fix this?
I would start from changing type int to pid_t for process identifiers, e.g.:
pid_t process_1;
and then would change:
process_1 = fork();
process_2 = fork();
process_3 = fork();
process_4 = fork();
to
pid_t pid = fork();
if (pid) {
process_1 = pid;
pid = fork();
}
if (pid) {
process_2 = pid;
pid = fork();
}
if (pid) {
process_3 = pid;
pid = fork();
}
if (pid)
process_4 = pid;
the idea is that we do fork() only in the parent process and skip forking in a child process. Otherwise your code forks processes as a tree, each child and parent processes call the next fork() after the previous, then their children do the same and so on four times.
The code above does not check if fork() returns the error code (-1). In the ideal world it is strongly recommended.
From the fork(2) man page:
Return Value
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the
parent, no child process is created, and errno is set appropriately.
Related
the following c program takes inputs for a 2D - array, and then takes a value n and multiplies every element by n. the child process iterates through the matrix, opens the file named sharedfile and then writes the value into the file. the parent process then open sharedfile and reads the values and prints them. I know there are probably better ways to accomplish this but this is the method we are learning currently.
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[]){
int row = 0;
int column = 0;
if(argc > 2){
row = atoi(argv[1]);
column = atoi(argv[2]);
}
int *A = (int *) malloc((row * column) * sizeof(int));
int i, j;
printf("Enter the matrix elements:\n");
for (i = 0; i < row; i++) {
for (j = 0; j < column; j++) {
printf("A[%d,%d] = ", i, j);
scanf("%d", A + i * column + j); //matrix elements is stored in row-wise
}
printf("\n");
}
enter n
int n = 0;
printf("Enter a number:");
scanf("%d", &n);
child process code:
char sharedfile[] = "child_result.txt";
for(int i = 0; i < row; ++i){
pid_t pid = fork();
if (pid == -1){//not able to create child
printf("parent PID %d => \n", getpid());
int Y[1000];
for (j = 0; j < column; j++) {
Y[j] = n * (*(A + i * column + j));
int fd = open(sharedfile, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
int byte_write = write(fd,Y,sizeof(Y));
printf("%d * A[%d,%d] = %d\n", n, i, j,byte_write);
close(fd);
exit(0);
}
}
else if (pid == 0) {//child
printf("child%d PID: %d \n", i, getpid());
int Y[1000];
for (j = 0; j < column; j++) {
Y[j] = n * (*(A + i * column + j));
int fd = open(sharedfile, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
int byte_write = write(fd,Y,sizeof(Y));
printf("%d * A[%d,%d] = %d\n", n, i, j,byte_write);
close(fd);
exit(0);
}
}
parent process code:
int child_exit;
wait(&child_exit);
printf("Final matrix elements:\n");
for (i = 0; i < row; i++) {
for (j = 0; j < column; j++) {
int fd = open(sharedfile,O_RDONLY);
int Y[1000];
int byte_read = read(fd,Y,sizeof(Y));
printf("A[%d,%d] = %d\n", i, j, byte_read);
close(fd);
}
printf("\n");
}
exit(0);
}
}
output if I enter n = 2 for a 2d array = {{1,2,3},{4,5,6}}. the result is 4 no matter what input values I enter, what's going wrong here?
Enter a number:2
child0 PID: 31930
2 * A[0,0] = 4
Final matrix elements:
A[0,0] = 4
A[0,1] = 4
A[0,2] = 4
A[1,0] = 4
A[1,1] = 4
A[1,2] = 4
I need to create a program that gets a dynamic matrix and changes it to one dimension, for example 4x4 matrix will give 16 arrays length, where each index has a odd or even number, matching the index itself. The threads needs to go over the matrix at the same time and copy the odd and even numbers to the correct places in the array. The main thread needs to wait for the rest of them to finish before printing the array and every value with its respective thread. It should come out like this
We managed to fix the segmentation fault that kept happening, but now we need to set it so that each thread runs right after the other but instead each thread runs 4 times and then it switches to a different one. How can I change it so it'll run as asked?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#define CORE 4
int N;
int odd = 1;
int even = 0;
typedef struct my_thread {
int** matrix;
int* resArray;
int threadId;
int strart_raw;
int strart_cal;
int end_raw;
int end_cal;
int counter;
} my_thread;
void* createArray(struct my_thread* thread);
void main() {
pthread_t th[CORE];
int s_r = 0, s_c, e_r, e_c;
int i, j, lines, columns, * intMatrix;
printf("Type the N for the N*N matrix:\t");
scanf("%d", &N);
int size = N * N;
int result_Array[N * N];
int retcode;
int interval = size / CORE;
int matrix_build_counter = 1;
intMatrix = (int*)malloc(N * N * sizeof(int));
for (i = 0; i < N; ++i)
{
for (j = 0; j < N; ++j)
{
intMatrix[i * N + j] = matrix_build_counter;
matrix_build_counter++;
}
}
printf("The matrix:\n");
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
printf("%d ", intMatrix[i * N + j]);
}
printf("\n");
}
struct my_thread thred_obj_array[CORE];
for (int i = 0; i < CORE; i++) {
thred_obj_array[i].matrix = &intMatrix;
thred_obj_array[i].resArray = result_Array;
thred_obj_array[i].threadId = i;
thred_obj_array[i].strart_raw = (int)((i * N) / CORE);
thred_obj_array[i].end_raw = (int)(((interval * (i + 1)) / N));
thred_obj_array[i].strart_cal = ((interval * i)) % N;
thred_obj_array[i].end_cal = ((interval) * (i + 1));
thred_obj_array[i].counter = (int)floor((interval)*i);
}
for (int i = 0; i < CORE; i++) {
retcode = pthread_create(&th[i], NULL, createArray, &thred_obj_array[i]);
if (retcode != 0) {
printf("Create thread failed with error %d\n", retcode);
}
}
printf("done");
for (int i = 0; i < CORE; i++) {
pthread_join(th[i], NULL);
}
printf("the result array is: ");
for (int i = 0; i < N * N; i++) {
printf("%d ", result_Array[i]);
}
}
void* createArray(struct my_thread* thread) {
int j;
for (int i = thread->strart_raw; i < N; i = i * sizeof(int) * N) {
for (j = thread->strart_cal; j < N; j++) {
printf("I am thread: %d And my value is: %d , (%d,%d)\n", thread->threadId, (*thread->matrix + i * N)[j], i, j);
if (((*thread->matrix + i * N)[j]) % 2 == 0) {
thread->resArray[even] = (*thread->matrix + i * N)[j];
even += 2;
printf("-----%d ---even---\n", even);
}
else {
thread->resArray[odd] = (*thread->matrix + i * N)[j];
odd += 2;
printf("---%d ---odd--\n", odd);
}
(thread->counter)++;
if (thread->counter == thread->end_cal) {
return;
}
}
thread->strart_cal = 0;
}
}
I am trying to understand how fork in c work. The problem that I am trying to solve is; given f(upper), I am trying to find f(1) + f(2) + .. f(upper).
I wanted to do multi process programming to have fork each child process and have each child process calculate f(x).
So f(1) , f(2) ... f(upper) is calculated by each child process.
The parent process should calculate following f(1) + .. + f(upper).
Here is my code
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include<sys/shm.h>
#include<sys/ipc.h>
int upper = 0;
int n = 0;
int main(int argc, char*argv[]){
pid_t pid;
if(argc != 2){
printf("Input one argument");
return -1;
}
upper = atoi(argv[1]);
int segment_id;
int *s;
pid_t *pids;
pids = (pid_t *) malloc(sizeof(int) * upper);
s = (int *) malloc(sizeof(int) * upper);
key_t key = 4141;
if((segment_id = shmget(key, upper * sizeof(int), IPC_CREAT | 0667))< 0) perror("shmget: failure");
if((s = shmat(segment_id, NULL, 0)) == (char *) -1){
perror("shmat : failure");
exit(1);
}
for(int i = 1; i <= upper; i++){
pid = fork();
if(pid == 0) {
n = i;
break;
}
pids[i] = pid;
}
if(pid > 0){
wait(1 * upper);
int totalSum;
for(int i = 0; i < upper; i++){
totalSum += s[i];
}
printf("Total sum = %d", totalSum);
} else {
sleep(2);
int sum = 0;
for(int i = 0; i <= n; i++){
sum += i;
}
s[n - 1] = sum;
printf("n => %d : sum %d\n", n, sum);
}
}
However whenever I try to run this program with argument more than 6.
I get Invalid argument error.
You are writing outside of the bounds of pids
pids = (pid_t *) malloc(sizeof(int) * upper);
...
for(int i = 1; i <= upper; i++){
pid = fork();
if(pid == 0) {
n = i;
break;
}
pids[i] = pid; /* Here */
}
Change to
for(int i = 1; i < upper; i++){
i am storing data in variable in child process and when i get value outside child process it returns me garbage value. But when i get value of variable (that i stored in the variable in the child process) in the child process it gives me correct value.
My code is given below. Thanks in advance.
#include <stdio.h>
#include <unistd.h>
void getValues();
void printValues();
int main()
{
int cpid, i = 0, j = 0, mat1[4], mat2[4], mat3[4], mat4[4], mat[4], sum1[4], sum2[4];
//get values in all matrixes.
for(i=0; i < 4; i++)
{
printf("\nEnter value %d in matrix 1: ", i+1);
scanf("%d", &mat1[i]);
}
for(i=0; i < 4; i++)
{
printf("\nEnter value %d in matrix 2: ", i+1);
scanf("%d", &mat2[i]);
}
for(i=0; i < 4; i++)
{
printf("\nEnter value %d in matrix 3: ", i+1);
scanf("%d", &mat3[i]);
}
for(i=0; i < 4; i++)
{
printf("\nEnter value %d in matrix 4: ", i+1);
scanf("%d", &mat4[i]);
}
//print values of all matrixes.
printf("\nMatrix 1:\n");
for(i=0; i < 4; i++)
{
printf("%d\t", mat1[i]);
if(i == 1)
{
printf("\n");
}
}
printf("\n\nMatrix 2:\n");
for(i=0; i < 4; i++)
{
printf("%d\t", mat2[i]);
if(i == 1)
{
printf("\n");
}
}
printf("\n\nMatrix 3:\n");
for(i=0; i < 4; i++)
{
printf("%d\t", mat3[i]);
if(i == 1)
{
printf("\n");
}
}
printf("\n\nMatrix 4:\n");
for(i=0; i < 4; i++)
{
printf("%d\t", mat4[i]);
if(i == 1)
{
printf("\n");
}
}
cpid = fork();
if(cpid < 0)
{
printf("\n\nFaild!\n\n");
}
if(cpid == 0)
{
for(i=0; i < 4; i++)
{
sum1[i] = mat1[i] + mat2[i];
}
}
else
{
for(i = 0; i <=10000; i++)
{for(j = 0; j<=10000; j++){}}
for(i=0; i < 4; i++)
{
sum2[i] = mat3[i] + mat4[i];
}
for(i=0; i < 4; i++)
{
mat[i] = sum1[i] + sum2[i];
}
printf("\nSum of All Matrixes:\n");
for(i=0; i < 4; i++)
{
printf("%d\t", mat[i]);
if(i == 1)
{
printf("\n");
}
}
}
}
You seem to be confused about how processes work. When a parent forks a child that child has a copy of the parent's address space(heap & stack). However, after that point they exist as separate entities; any changes to the address space in the child isn't reflected in the parent's address space and vice versa. The only way to share resources between processes is either via inter-process communication API's in the OS(nasty performance losses due to constant system interrupts) or shared memory segments(via mmap or shmem). Because of this you are mostly likely going to want to use threads instead of processes; a great resource for learning about threads can be found here: https://computing.llnl.gov/tutorials/pthreads/ .
A rough example on how your specified query could be done is shown below(not really sure what you are trying to achieve with the actual code, but nonetheless.):
#include <pthread.h>
#include <stdlib.h>
typedef struct {
int size;
int matrix[];
} MatrixStruct;
void *thread_matrix_calc(void *arg) {
//Cast arg to the struct it points at
MatrixStruct *matrix = (MatrixStruct *)arg;
//Pull variables from that struct
int matrix_size = matrix->size;
int (*matrix_arry)[matrix_size] = matrix->matrix;
/*
* Code for child matrix manipulation goes here...
*/
return NULL;
}
int main(void) {
//Initialize all matrices and summations
MatrixStruct *child_matrix = malloc(sizeof(int) + (MATRIX_SIZE * sizeof(int));
//Initialize and start child thread
pthread_t child_thread;
int child_thread_init = pthread_create(&child_thread, NULL, &thread_matrix_calc, (void *)child_matrix);
//Ensure initialization was successful
if(child_thread_init < 0) exit(EXIT_FAILURE);
/*
* Code for parent matrix manipulation goes here...
*/
//Join child thread to ensure child has finished manipulating it's matrix.
pthread_join(child_thread, NULL);
/*
* At this point both the parent and child manipulated matrices can be accessed
* in the remaining thread.
*/
return 0;
}
Note: code wasn't compiled and is given only as a semantical demonstration of POSIX threads.
For input of n = 10, i am getting a weird output :
pid = 31456
Sum of Odd series : 25
pid = 31456
Sum of Even series : 30
pid = 31456
Code
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
pid_t child_pid;
int i, j, k, n;
int sum;
//printf("Enter the last number of series : ");
scanf("%d", &n);
printf("pid = %d\n", getpid());
for(i = 0; i < 2; i++)
{
child_pid = fork();
if (child_pid < 0)
{
printf("Failed to create child process . . .");
return 1;
}
else if (child_pid == 0)
{
if (i == 0) //find the sum of odd series
{
sum = 0;
for(j = 1; j <= n; j += 2)
sum += j;
printf("Sum of Odd series : %d\n", sum);
exit(0);
}
else if (i == 1) //find the sum of even series
{
sum = 0;
for(j = 2; j <= n; j += 2)
sum += j;
printf("Sum of Even series : %d\n", sum);
exit(0);
}
}
else
{
wait(&child_pid);
}
}
return 0;
}
Ideone link : ideone.com/TyIkJa
You will have to change your code as below.
if (childs[i] == 0)
{
if (i == 0) //find the sum of odd series
{
for(j = 1; j <= n; j += 2)
sum += j;
printf("Sum of odd series : %d\n", sum);
exit(0);
}
else if (i == 1) //find the sum of even series
{
for(k = 2; k <= n; k += 2)
sum += k;
printf("Sum of even series : %d\n", sum);
exit(0);
}
else
{
wait(&childs[i]);
}
The reason is both children and parent have their own copies of sum. So when you are ending the parent still has sum=0 ,but these values are updated for "sum" of child1 and "sum" of child2.
When you fork a process, then parent and child are initially
more or less exact copies, including the values of variables,
except for the return code of fork().
But the key word there is copies.
Those two processes are now independent and variables,
"global" or not, *are not connecte*d in any way.