멀티프로세스에서 파일잠금은 어떻게 구현?

익명 사용자의 이미지

서버구조는 입출력다중화로 만들었습니다.
select를 쓰고 waitpit()와 fork()를 사용해서 구현했습니다.
클라이언트 100개에서 서버로 명령을 보내면 메세지는
잃어버리지 않고 자식 프로세스들이 줄기차게 돌아갑니다.

그런데 자식 프로세스에서 문제가 있습니다. 기본적으로
여러가지 일들이 있는다. a함수 b함수 c함수가 있다고 하면
이함수들이 shared_function()를 씁니다. 파일 입출력을 구현한 기본 함수
입니다.
문제는 shared_function() 이 임시 파일을 쓰는데 다른 프로세스에서 가로
채기가 되어 엉뚱한 일이 실행되곤합니다.
해서 이 shard_function() 에 락을 걸어야 겠다고 생각했습니다. 해서
my_lock()과 my_unlock()를 구현했습니다.
my_lock(){
while(open("/tmp/proc1.swf",O_CREAT | ,etc
sleep(1);
/* 책 찾아 가면서 동시에 열리지 않는거랑 여러가지로 만들었습니다.
위에 여는 옵션은 잘 생각이 안나네요
*/
}
unlock(int fd){
close(fd
}

위처럼 락을 거니 거의 80%는 제대로 동작을 했습니다.
아 이래도 안돼는 구나.., sleep(5)로하니 거의 95%정도가
제대로 되고요.. 결론은 이렇게 하면 안되겠구나 입니다.
이 위쪽에도 락을 걸어보았습니다. a()함수 b()함수등등
그래도 답이 아닌거 같더군요.

지금 서버를 시작하고 클라이언트 여러개를 실행한후에
프로세스를 보면
pstree------ server ------ (*5)server
이렇게 됩니다.

-------------------------------------------------------------
클라이언트/서버 모델의 최고의 모델은 비봉쇄입출력이라고 스티븐
아저씨가 말하시더군요.
질문1.제가 짠 프로그램에서 세마포를 사용해야 해결되는 문제인가요?
다른 좋은 방법이라도?
질문2.클라이언트/서버 모델이 지금의 모델로는 1024이상의 클라이
언트 처리가 불가능한지요? 만약에 더 이상의 처리를 하려면 어떤
모델로 만들어야 하는지 궁금합니다.

읽어주셔서 감사합니다.

익명 사용자의 이미지


한클라이언트에 하나의 자식 프로세스를 할당해서...
채팅서버같은걸 구현하신것 같은뎅.. 맞는지.. --a

굳이 화일에 써야 할까요? 꺙 열어논 소켓으로 데이타를 뿌리시는건 어떨
지.. 프로세스간 통신에 쓰라구 모 여러가지 - 세마포, 파이프.... -가 있
지만 그냥 소켓으로 통신하는것두 좋을것 같습니다만...

익명 사용자의 이미지

네 채팅 서버라면 그렇게 구현하면 됩니다.
그런데 채팅이 아니라 다른 작업하는 프로세스거든요
자식 프로세스가 많은데 이놈들 동기화 시키는게
공유메모리, 세마포, 뮤텍스가 있는 걸로 압니다.
세마포도 뮤텍스도 쓰는 방법을 찾는데 잘 못찾겠네요(기본적인건
찾아 보고 ,또 어려운건 책을 봐도 이해가 잘 안가서요)

예를 들어 머 메인에서 뮤텍스를 이니셜해주고 자식 프로세스에서
그 이니셜해준 뮤텍스를 락을 걸고 풀고 하시오. << 말은 쉬운데
제 머리로는 영 해결방법이 안떠오르네요. 해결방법이 있다면
자식 프로세스 만들때 함수에 뮤텍스 구조체 넘겨주는 방법이 있을것
같긴한데 그러자면 소스 다 고쳐야 하고, 그리 좋은 방법 같지는않고요
자식에서 뮤텍스 이니셜하면 전혀 다른 뮤텍스가 되니까 이것도 아니고요

익명 사용자의 이미지

1. Mutex...Mutex는 multi thread용이지 multi process용이 아니라는 사실
을 명심하시길...

만약 mutex를 공유하려면 Shared memory에 mutex를 올려놓아야 하는데
기술적으로 어렵죠?

가능하다 해도 Mutex는 결정적인 문제가 있습니다.

lock을 건 Process가 lock을 풀지 못하고 죽는 경우 그 Mutex를 쓰는
모든 프로세스는 얼어버립니다.

그러니 않 되겠죠?

2. Semaphore
Multi Process 환경에서 사용할 수 있고, 위에서 열거한 문제가 없습
니다.(다행이도)

근데 만약 100개가 동시에 Semaphore를 핸들링하는 경우에 속도 문제
가 걸릴수도 있겠죠.

근데 속도가 빨라지게 하려고 여러개의 Semaphore를 쓰게되면...

보통 Semaphore의 시스템에서의 갯수 제한이 60개니까...이것저것 쓰고
나면 가용한 Semaphore는 약 30개 정도일 수 있습니다.

그러니 속도 높인다고 Semaphore의 갯수를 늘리는 것은 아주 않 좋은
선택이죠.

결론은 버킹검이라고 Semaphore 하나로 여러개의 Semaphore를 쓰는 방
법이 있습니다.

Posix에서는 물론 System V에서도 가능. R Stevens Network programmi
ng II를 보시면 되겠습니다.

익명 사용자의 이미지

;1.Mutex...Mutex는 multi thread용이지 multi process용이 아니라는 사실
; 을 명심하시길...

간혹이긴 하지만 process들을 위해서 사용하기도 합니다.
그리고 shared 방법은 여러가지가 있습니다.
그중 대표적인게 공유메모리일뿐이죠, file(mmap)을 통해서도 간단히
구현 됩니다. 이렇게 하면 여러 프로세스들이 공유할수 있죠.

예제 프로그램 *)
#define _REENTRANT
#include
#include
#include
#include
#include
#include
#define INTERPROCESS_FILE "ipc-sharedfile"
#define NUM_ADDTHREADS 12
#define NUM_SUBTRACTTHREADS 10
#define INCREMENT '0'
#define DECREMENT '1'
typedef struct {
mutex_t Interprocess_mutex;
int Interprocess_data;
} buffer_t;
buffer_t *buffer;

void *add_interprocess_data(), *subtract_interprocess_data
();
void create_shared_memory(), test_argv();
int zeroed[sizeof(buffer_t)];
int ipc_fd, i=0;

void
main(int argc,char * argv[]) {
test_argv(argv[1]);

switch (*argv[1]) {
case INCREMENT
create_shared_memory();
ipc_fd = open(INTERPROCESS_FILE, O_RDWR);
buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
PROT_READ|PROT_WRITE, MAP_SHARED,
ipc_fd, 0);
buffer->Interprocess_data = 0;
mutex_init(&buffer->Interprocess_mutex,
USYNC_PROCESS,0);
for (i=0; i< NUM_ADDTHREADS; i++)
thr_create(NULL, 0, add_interprocess_data, argv
[1],
0, NULL);
break;
case DECREMENT
while((ipc_fd = open(INTERPROCESS_FILE, O_RDWR))
== -1)
sleep(1);
buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
PROT_READ|PROT_WRITE, MAP_SHARED,
ipc_fd, 0);
for (i=0; i< NUM_SUBTRACTTHREADS; i++)
thr_create(NULL, 0, subtract_interprocess_data,
argv[1],
0, NULL);
break;
} /* end switch */

while ((thr_join(NULL,NULL,NULL) == 0));
} /* end main */

void *add_interprocess_data(char argv_1[]) {
mutex_lock(&buffer->Interprocess_mutex);
buffer->Interprocess_data++;
sleep(2);
printf("%d is add-interprocess data, and %c is argv1
\n",
buffer->Interprocess_data, argv_1[0]);
mutex_unlock(&buffer->Interprocess_mutex);
return NULL;
}

void *subtract_interprocess_data(char argv_1[]) {
mutex_lock(&buffer->Interprocess_mutex);
buffer->Interprocess_data--;
sleep(2);
printf("%d is subtract-interprocess data, and %c is
argv1\n",
buffer->Interprocess_data, argv_1[0]);
mutex_unlock(&buffer->Interprocess_mutex);
return NULL;
}

void create_shared_memory() {
int i;
ipc_fd = creat(INTERPROCESS_FILE, O_CREAT|O_RDWR );
for (i=0; i zeroed[i] = 0;
write(ipc_fd, &zeroed[i],2);
}
close(ipc_fd);
chmod(INTERPROCESS_FILE, S_IRWXU|S_IRWXG|S_IRWXO);
}

void test_argv(char argv1[]) {
if (argv1 == NULL) {
printf("use 0 as arg1 for initial process\n \
or use 1 as arg1 for the second process\n");
exit(NULL);
}
}

;2. Semaphore
구현방법상의 문제입니다. 만약 순차적인 접근을 위한 제어라면
성능상 큰 문제가 되지 않습니다.

참고
이외에 다양한 예제가 unpv22e.tar 에 있습니다.
예기에는 sem에 관련한 거의 모든 예제들이 존재한다고
보면 됩니다.

익명 사용자의 이미지

말씀하신대로 mmap를 이용해서도 mutex공유는 가능하겠죠.

근데 mutex를 여러개의 프로세스가 공유할때 하나의 프로세스가 그 잠근
뮤텍스를 풀지 못하는 경우(예를 들면 SIGINT를 받아서 죽는 경우), 이
뮤텍스를 이용하는 모든 프로세스가 한꺼번에 홀딩될 수 있는 가능성이
존재하지 않습니까?

세마포의 경우에는 이런 경우가 발생하지 않더군요.

그래서 제가 여쭤보는 것은 뮤텍스를 여러 프로세스가 공유한다고 했을때
하나의 프로세스가 뮤텍스를 잠그고나서 미처 풀지 못하는 경우를 방지할
그 어떤 방법이 있는지 궁금합니다.

만약 그런 방법이 있다면 여러프로세스가 자원공유를 하더라도 아무런 문
제도 없고 갯수제한도 없으니 정말 행복할텐데요...

그럼, 좋은 가르침 부탁드립니다.

익명 사용자의 이미지

그냥 참고 사항인데요, 솔라리스와 달리
우울하게도 현재 리눅스 pthread 라이브러리는
프로세스 공유 뮤텍 지원이 안됩니다.

http//kltp.kldp.org/stories.php?story=01/07/05/2982955

리눅스에서 대안이라면 semget 이 있을 것 같습니다.

익명 사용자의 이미지

Test를 해봐야 하겠네요.
아직은 답변을 하기가.....

익명 사용자의 이미지

2.2 때의 이야기 아닌가요 ?.
2.4 에서는 어떻지..., 자료를 봐야 알겠네요. !!
관련 자료 있으면 부탁합니다.

익명 사용자의 이미지

저도 2.4에서는 해결됐을까해서 제작자에게 문의해 봤는데요.
2.4에서도 안되고, 언제 해결될 지 기약할 수도 없다더라구요.
리눅스 커널의 근본적 구현문제 때문이랍니다.

익명 사용자의 이미지

답변 감사드립니다. 많은 도움이 되었습니다.
그리고 이번기회에 네트웍 프로그래밍 볼륨2 사기로 마음 먹었습니다.

아 그리고 아이비엠에서 누군가가 분석해논 자료가 있던데 그냥 참고 삼
아 읽어보세요.
rt5.html?dwzone=linux" target="netnet">[새창]클릭하세요

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.