c언어 부모 자식 프로세스 변수 공유

가지@Google의 이미지

전역변수로 선언된 sum과 step을 부모 자식 프로세스에서 둘다 사용하고 있습니다.

근데 공부하다 보니 서로 다른 프로세스 간 변수 공유가 안된다고 해서 질문합니다.

파이프 형식으로 변수를 공유하는 걸 생각했는데 생각보다 잘 안되더라구요.

밑에는 파이프를 사용하지 않은 소스코드 입니다. child에서 저장된 전역변수 step과 sum을 parent 프로세스에서도 사용하고 싶습니다.

thread를 사용하지 않고 부모 자식 프로세스간에 변수를 공유하고 싶습니다.

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
 
 
#define MAX_PROCESSES 4 
#define MAX_LEN 5
 
void child();
void parent();
int sum[MAX_PROCESSES] ={0, };
int step = 0;
 
int main(){
    pid_t pid;
    pid = fork();
    int i=0;
    int status;
    int count = MAX_PROCESSES/2;
 
 
    if(pid == -1){
	printf("can't fork, error\n");
	exit(0);
    }
    if(pid == 0){ //child
     	for(i=0; i<MAX_PROCESSES;i++){
                child((void*)i);
    	}
  	exit(0);
 
    }
    else{ //parent
	wait(&status);
 
        while(count){
            for(i=0;i<count;i++){
                    parent((void*)i);
            }
            count = count/2;
        }
        exit(0);
    }
 
    printf("FINAL RESULT: %d\n",sum[0]);
 
    return 0;
}
 
void child(void *arg){
	struct File *f_read;
	char buffer[MAX_LEN];
	int list = (int)arg;
	int i = list*2;
	int first = 0;
	int second = 0;
	int line_count = 0;
 
	f_read=fopen("temp.txt","r");
	if(f_read==NULL){
		printf("file read error!\n");
		return (void*)0;
	}
	while(fgets(buffer,MAX_LEN,f_read)!=NULL){
		if(line_count == i){
			first = atoi(buffer);
			second = atoi(fgets(buffer,MAX_LEN,f_read));
		}
		line_count++;
	}
	fclose(f_read);
 
	sum<ul class="bb-list"> = first + second;
	printf("step: %d, %d + %d = %d\n",++step, first, second, sum<ul class="bb-list">);
	return (void*)1;
}
 
void parent(void *arg){
	int list = (int)arg;
	int first = list*2;
 
	printf("step: %d, %d + %d = ",++step,sum[first],sum[first+1]);
	sum<ul class="bb-list"> = sum[first] + sum[first+1];
	printf("%d\n",sum<ul class="bb-list">);
	return (void*)1;
}

<출력결과>

step: 1, 1 + 2 = 3
step: 2, 3 + 4 = 7
step: 3, 5 + 6 = 11
step: 4, 7 + 8 = 15
step: 1, 0 + 0 = 0
step: 2, 0 + 0 = 0
step: 3, 0 + 0 = 0

<기대하는 출력결과>

step: 1, 1 + 2 = 3
step: 2, 3 + 4 = 7
step: 3, 5 + 6 = 11
step: 4, 7 + 8 = 15
step: 5, 3 + 7 = 10
step: 6, 11 + 15 = 26
step: 7, 10 + 26 = 36
FINAL RESULT: 36

++추가로 temp.txt에 있는 글은 다음과 같습니다.
1
2
3
4
5
6
7
8

익명 사용자의 이미지

1. 원하는 동작을 하는 프로그램을 thread로는 작성하실 수 있습니까?

해 본 적 없다면 이걸 먼저 해 보시는 걸 추천 드립니다. 전역변수가 공유되는 상황에서조차 신경써야 할 일이 무척 많습니다.

2. 가장 trivial한 방법은 그냥 shared memory를 잡는 겁니다.

mmap 같은 거 알아보세요.

https://blog.minhazav.dev/memory-sharing-in-linux/

익명 사용자의 이미지

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/shm.h>
 
#define MAX_PROCESSES 4 
#define MAX_LEN 5
 
void child();
void parent();
int sum[MAX_PROCESSES] = {0, };
 
int main(){
    pid_t pid;
    int i=0;
    int status;
    int count = MAX_PROCESSES/2;
    int value;
 
    int shm_id = shmget((key_t)1234, 1024, IPC_CREAT | 0666);
    if (shm_id == -1) perror("shmget");
    int *shm_addr = (int*) shmat( shm_id, NULL, 0);
    if (shm_addr == (int*) -1) perror("shmat");
    int *step = shm_addr;
    int *done = shm_addr + 1;
    int *result = shm_addr + 2;
 
    pid = fork();
    if (pid == -1) {
        printf("can't fork, error\n");
        exit(0);
    }
    if (pid == 0) { //child
        for (i=0; i < MAX_PROCESSES; i++) {
            child(i, step, done, result);
        }
        *done = 1;
        exit(0);
    }
    // parent
    parent(step, done, result);
    int val1 = *result++;
    int val2 = *result++;
    int res = val1 + val2;
    printf("P step: %d, %d + %d = %d\n", (*step)++, val1, val2, res);
    printf("FINAL RESULT: %d\n", res);
    shmctl(shm_id, IPC_RMID, NULL);
    return 0;
}
 
void child(int arg, int *step, int *done, int *result) {
    FILE *f_read;
    char buffer[MAX_LEN];
    int list = arg;
    int i = list*2;
    int first = 0;
    int second = 0;
    int line_count = 0;
 
    f_read = fopen("temp.txt","r");
    if (f_read == NULL)
        printf("file read error!\n");
    while (fgets(buffer, MAX_LEN, f_read) != NULL) {
        if (line_count == i) {
            first = atoi(buffer);
            second = atoi(fgets(buffer, MAX_LEN, f_read));
        }
        line_count++;
    }
    fclose(f_read);
 
    int sum_add = first + second;
    printf("C step: %d, %d + %d = %d\n", (*step)++, first, second, sum_add);
    *(result + arg) = sum_add;
}
 
void parent(int *step, int *done, int *result) {
    while (! *done) ;
    int loop = *step / 2;
    int val1, val2, sum_add;
    int *result_bak = result;
    for (int i = 0; i < loop; ++i) {
        val1 = *(result++);
        val2 = *(result++);
        sum_add = val1 + val2;
        printf("P step: %d, %d + %d = %d\n", (*step)++, val1, val2, sum_add);
        *result_bak++ = sum_add;
    }
}
 
--------------------------------------------
 
$ gcc test.c -lrt
 
$ ./a.out 
C step: 0, 1 + 2 = 3
C step: 1, 3 + 4 = 7
C step: 2, 5 + 6 = 11
C step: 3, 7 + 8 = 15
P step: 4, 3 + 7 = 10
P step: 5, 11 + 15 = 26
P step: 6, 10 + 26 = 36
FINAL RESULT: 36
가지@Google의 이미지

제가 공부하다 막막해서 커뮤니티의 필요성을 느꼈는데 정말로 친절하신 분들이 많네요
도움주신 코드를 보다 제 코드를 보니 제가 다 부끄러워지긴 하는데 정말로 감사드립니다
더욱더 공부해서 깔끔한 코드 쓸 수 있게 노력해볼게요!

shared memory도 찾아보고 있었는데 처음 보는 메소드라 어떻게 활용해야 할지 잘 몰랐었는데 확실히 코드로 보여주시니 이해가 되네요 감사합니다

++thread는 인터넷에서 자료 찾아보고 성공했었습니다!!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.