お世話になります。
現在、Cygwin にて共有メモリについて学習しています。そこで質問なのですが、
親プロセスで新規作成した共有メモリに、子プロセスでアタッチし、値を設定、デタッチしようとしているのですが、
子プロセスでアタッチをすると異常終了してしまいます。
子プロセスからアタッチはできると思っているのですが、どこがいけないのでしょうか。
どうか、よろしくお願いします。
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
int main(void)
{
int id;
int i;
/* 共有メモリ新規作成 */
id = shmget(IPC_PRIVATE, 512, 0666);
if(id == -1) {
perror("main-shmget ");
exit(-1);
}
/* 子プロセスを生成 */
if (fork() == 0) {
char *adr;
printf("子プロセス開始\n");
/* プロセスアドレス空間にアタッチ */
adr = (char *)shmat(id, NULL, 0); // ★ ココでアタッチエラー
if(adr == (void *)-1) {
perror("子プロセス - shmat ");
exit(-1);
}
/* 共有メモリ・セグメントに文字列をコピー */
strcpy(adr, "Hello\n");
/* プロセスアドレス空間をデタッチ */
if(shmdt(adr) == -1) {
perror("子プロセス - shmdt ");
exit(-1);
}
printf("子プロセス終了\n");
exit(0);
}
/* 親プロセス-子の終了を待つ */
wait(NULL);
/* 共有メモリを破棄 */
if (shmctl(id, IPC_RMID, NULL) == -1){
perror("main-shmctl ");
exit(-1);
}
printf("親プロセス終了\n");
return 0;
}
子プロセスから共有メモリのアタッチ
-
yu-ichi
Re: 子プロセスから共有メモリのアタッチ
コードが見づらくてすみません。書き直します。
よろしくお願いします。
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
int main(void)
{
int id;
int i;
/* 共有メモリ新規作成 */
id = shmget(IPC_PRIVATE, 512, 0666);
if(id == -1) {
perror("main-shmget ");
exit(-1);
}
/* 子プロセスを生成 */
if (fork() == 0) {
char *adr;
printf("子プロセス開始\n");
/* プロセスアドレス空間にアタッチ */
adr = (char *)shmat(id, NULL, 0); // ★ ココでアタッチエラー
if(adr == (void *)-1) {
perror("子プロセス - shmat ");
exit(-1);
}
/* 共有メモリ・セグメントに文字列をコピー */
strcpy(adr, "Hello\n");
/* プロセスアドレス空間をデタッチ */
if(shmdt(adr) == -1) {
perror("子プロセス - shmdt ");
exit(-1);
}
printf("子プロセス終了\n");
exit(0);
}
/* 親プロセス-子の終了を待つ */
wait(NULL);
/* 共有メモリを破棄 */
if (shmctl(id, IPC_RMID, NULL) == -1){
perror("main-shmctl ");
exit(-1);
}
printf("親プロセス終了\n");
return 0;
}
Re: 子プロセスから共有メモリのアタッチ
Bad System Callは回避できているということですよね。
未確認ですが検索して見付けたページを紹介します。
http://d.hatena.ne.jp/haradats/20060504/p2
要約すると、
最後に念のためウインドウズを再起動したほうが良いでしょう。
(追記)
サービスの登録・起動の際は管理者権限が必要だそうです。
未確認ですが検索して見付けたページを紹介します。
http://d.hatena.ne.jp/haradats/20060504/p2
要約すると、
- CYGWIN環境変数にserverを追加
- cygserver-configコマンドを実行してウインドウズにサービスを登録
- net start cygserverもしくはcygrunsrv -S cygserverのコマンドラインでコマンドを実行してサービスを開始
最後に念のためウインドウズを再起動したほうが良いでしょう。
(追記)
サービスの登録・起動の際は管理者権限が必要だそうです。
-
yu-ichi
Re: 子プロセスから共有メモリのアタッチ
どうもありがとうございます。
cygserver ですが、下記の方法でcygserverを起動してから実行しています。
1. $ cygserver-config を実行
2. $ /usr/sbin/cygserver & を実行
ps でcygserverが動作していることを確認
3440 2396 3440 4188 0 1000 17:34:51 /usr/sbin/cygserver
その後、実行すると28行目でアタッチエラーとなり、その後cygserverが落ちてしまいます。
エラーは以下の通りです。
$ ./s
子プロセス開始
0 [unknown (0xF50)] cygserver 5472 exception::handle: Error while dumping state (probably corr
upted stack)
子プロセス - shmat : Invalid argument
0 [main] s 5560 transport_layer_pipes::connect: lost connection to cygserver, error = 2
0 [main] s 5560 transport_layer_pipes::connect: lost connection to cygserver, error = 2
[1]+ Segmentation fault (core dumped) /usr/sbin/cygserver
Bad system call
cygserver ですが、下記の方法でcygserverを起動してから実行しています。
1. $ cygserver-config を実行
2. $ /usr/sbin/cygserver & を実行
ps でcygserverが動作していることを確認
3440 2396 3440 4188 0 1000 17:34:51 /usr/sbin/cygserver
その後、実行すると28行目でアタッチエラーとなり、その後cygserverが落ちてしまいます。
エラーは以下の通りです。
$ ./s
子プロセス開始
0 [unknown (0xF50)] cygserver 5472 exception::handle: Error while dumping state (probably corr
upted stack)
子プロセス - shmat : Invalid argument
0 [main] s 5560 transport_layer_pipes::connect: lost connection to cygserver, error = 2
0 [main] s 5560 transport_layer_pipes::connect: lost connection to cygserver, error = 2
[1]+ Segmentation fault (core dumped) /usr/sbin/cygserver
Bad system call
Re: 子プロセスから共有メモリのアタッチ
とりあえずcygserverは直接起動するのではなく、ウインドウズのサービスとして起動してください。
cygserverの例外ハンドルのエラーとセグメンテーション違反はそれで消えます。
動作確認したところ、それでもshmatでコネクションをロストするというエラーは発生するので調べてみました。
Cygwinの仕様で、forkした子プロセスでアタッチ(shmat)/デタッチ(shmdt)することはできないようです。
ウインドウズではスレッドで実装されているためかと思います。
http://linuxgcc.sytes.net/sys013.php
↑こちらのページによると、親プロセス側でアタッチして得たポインタをそのままforkした子プロセスで共有メモリのアクセスに使えるようです。
こちらの方法はCygwinとUbuntuの両方で正常動作を確認できました。
cygserverの例外ハンドルのエラーとセグメンテーション違反はそれで消えます。
動作確認したところ、それでもshmatでコネクションをロストするというエラーは発生するので調べてみました。
Cygwinの仕様で、forkした子プロセスでアタッチ(shmat)/デタッチ(shmdt)することはできないようです。
ウインドウズではスレッドで実装されているためかと思います。
http://linuxgcc.sytes.net/sys013.php
↑こちらのページによると、親プロセス側でアタッチして得たポインタをそのままforkした子プロセスで共有メモリのアクセスに使えるようです。
こちらの方法はCygwinとUbuntuの両方で正常動作を確認できました。