No.1ベストアンサー
- 回答日時:
読み込み同士なら排他制御しなくてもいいですけど。
けど、誰かその共有メモリに書き込むプロセスやスレッドがいるはずなので、
共有ロックは必要なのでは。
No.4
- 回答日時:
冒頭のコメントにしたがって xyz.c および xyz2.c コンパイルし、./a.out で実行してください。
/* xyz.c with xyz2.c combination test program by gcc on Mac OSX
* compile: gcc xyz.c
* execution: ./a.out
* loop end: "!" + [return]
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include "okw.h"
#define CODE 999// 適当に変更のこと
#define OUT_FILE "data_list"// 〃
#define STDIN 0
#define STDERR 2
void handler(int);
int main(void) {
int shmid;
void *shmaddr;
int nread, n;
char command_line[64];
/* 共有メモリを確保する */
if (((shmid = shmget(CODE, sizeof(*ptr) + 2,
IPC_CREAT | S_IRUSR | S_IWUSR)) == -1)
|| ((shmaddr = shmat(shmid, NULL, 0)) == (char *)-1)) {
perror("Shared memory set");
exit(1);
}
/* 共有メモリに struct構造体をあてがう */
ptr = (struct set1 *)shmaddr;
/* 自身のプロセスIdを記録する */
ptr->id_number[PARENT] = getpid();
/* シグナルハンドラー登録 */
signal(SIGCONT, handler);
/* ↓ 手抜きです m(_ _)m
*(OUT_FILEにバックグランドで追加書き込み可に)
*/
ptr->flag[PARENT] = ON;
sprintf(command_line, "./xyz2 %d >>%s &", shmid, OUT_FILE);
if (system(command_line) != 0) {
perror("Shell command line");
exit(1);
}
/* プログラムサイズの大きな子プロセスの準備順延に配慮 */
fprintf(stderr, "Program setting now");
while (ptr->flag[PARENT] != OFF) {
fprintf(stderr, ".");
sleep(1);
}
fprintf(stderr, "\n\n");
do {
n = 0;
ptr->flag[OUTPUT] = OFF;
while (1) {
write(STDERR, "> ", 2);
if ((nread = read(STDIN, &ptr->buffer[n],
MEM_SIZE - n)) == -1) {
perror("Read line");
exit(1);
}
if (ptr->buffer[n] == '!') {
ptr->buffer[n] = '\0';/* '!' を削除する */
break;
} else
n += nread;
}
/* 子プロセスへ入力結果をHDDに並列出力ようシグナルを送信 */
ptr->flag[PARENT] == OFF;
kill(ptr->id_number[OUTPUT], SIGCONT);
/* 結果のターミナル出力 */
printf("buffer:\n");
printf("%s", ptr->buffer);
/* 作業継続の確認 */
write(STDERR, "> continue y/n? ", 16);
read(STDIN, command_line, 2);
/* HDD書き込み終了まで待機(dead_lockの回避)
*作業継続入力後も子プロセスが出力中なら1秒休む。
*ただし、出力が完了したならシグナル等で起こされる。
*/
while (ptr->flag[PARENT] != OFF)
sleep(1);
} while (*command_line == 'y' || *command_line =='Y');
/* 子プロセスのプログラム終了送信 */
ptr->flag[OUTPUT] = ON;
kill(ptr->id_number[OUTPUT], SIGCONT);
/* 共有メモリを解放する */
if (shmdt(shmaddr) == -1 || shmctl(shmid, IPC_RMID, 0) == -1) {
perror("Shared memory closed");
exit(1);
}
return 0;
}
/* 何もしないシグナル処理関数 */
void handler(int dummy){
;
}
--- ここまで
/* xyz2.c child process data output program by gcc on Mac OSX.
* compile : gcc xyz2.c -o xyz2
* execution: シェルプロンプトから起動しないこと。
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include "okw.h"
void handler(int);
int main(int argc, char *argv[]) {
int shmid;
void *shmaddr;
/* 共有メモリを親プロセスから受け継ぐ */
shmid = atoi(argv[--argc]);
if ((shmaddr = shmat(shmid, NULL, 0)) == (char *)-1) {
perror("Shared menory set");
exit(1);
}
/* 共有メモリに struct構造体をあてがう */
ptr = (struct set1 *)shmaddr;
/* 自身のプロセスIdを記録する */
ptr->id_number[OUTPUT] = getpid();
ptr->flag[OUTPUT] = OFF;
/* シグナルハンドラー登録 */
signal(SIGCONT, handler);
/* 親プロセスに「スタンバイ ok!」を知らせる */
ptr->flag[PARENT] = OFF;
kill(ptr->id_number[PARENT], SIGCONT);
while (1) {
/* 親プロセスからのシグナルを待つ */
pause();
if (ptr->flag[OUTPUT] != OFF)
break;/* 出力しないならループ脱出 */
else {
/* 「出力中!」の看板を掲げ、出力する */
ptr->flag[PARENT] = ON;
printf("%s", ptr->buffer);
/* バッファリングせずに強制排出 */
fflush(stdout);
/* 「出力中!」の看板を降ろし、親プロセスにシグナルを送付 */
ptr->flag[PARENT] = OFF;
kill(ptr->id_number[PARENT], SIGCONT);
}
}
/* 共有メモリを切り離す */
if (shmdt(shmaddr) == -1) {
perror("Shared menory closed");
exit(1);
}
return 0;
}
/* 何もしないシグナル処理関数 */
void handler(int dummy){
;
}
---- ここまで
/* 共通事項リストアップ・定義等ヘッダーファイル
* file name: okw.h
*
*プロセス間での共通項を列挙し、不用意な間違いをなくす。
*そして、Cの線形プログラミング構造を積極的に活用する。
*/
#define MEM_SIZE 512// 共有メモリのサイズ
#define PROCS 3// 全プロセス数
#define OUTPUT 1// 出力専門の子プロセス
#define PARENT 0// 親プロセス
#define ON 1
#define OFF 0
struct set1 {
char buffer[MEM_SIZE];// data buffer
signed char flag[PROCS];// condition flag
pid_t id_number[PROCS];// process id code
} *ptr;
No.3
- 回答日時:
親プロセスのほうでデータを共有メモリに書き込み、表示しながら、子プロセスでは出力するプログラムを作成してみました。
環境は Mac OSX です。待機しているファイル出力プロセスにシグナルを送って同時に出力する場合は、kill()とpause()関数の間に出力プログラムを書けば良いと思います。書き込みは共有メモリに直接書き込んでいることから、子プロセスが書き出し完了まで待つようにしてみました。後は、これを応用すれば実現できると思います。
なお、スペースは2バイトスペースですので、半角に直して下さい。
/* xyz.c with xyz2.c combination test program by gcc on Mac OSX
* execution: ./a.out
* compile: gcc xyz2.c
* loop end: input "!"
*/
#include <stdio.h> /* for printf() */
#include <unistd.h> /* for getpid() */
#include <stdlib.h> /* for exit() */
#include <sys/types.h> /* for shared memory */
#include <sys/ipc.h> /* 〃 */
#include <sys/shm.h> /* 〃 */
#include <sys/stat.h>
#include <signal.h> /* for signal */
#define CODE 999 /* 適当に変更のこと */
#define OUT_FILE "data_list" /* 〃 */
#define MEM_SIZE 256 /* 読み込みサイズ */
#define PROCS 3 /* 全プロセス数 */
#define OUTPUT 1 /* 標準出力パス */
#define ON 1
#define OFF 0
#define STDERR 2 /* エラー出力パス */
struct set1 { /* xyz.c = xyz2.c を厳守 */
char buffer[MEM_SIZE]; /* data buffer */
signed char flag[PROCS]; /* condtion flag */
pid_t id_number[PROCS]; /* id code */
} *ptr;
int shmid; /* 共有メモリ関連 */
char *shmaddr; /* 〃 */
void no_ope(int);
int main(void) {
int nread;
char command_line[128];
if (((shmid = shmget(CODE, MEM_SIZE + sizeof(*ptr),
IPC_CREAT | S_IRUSR | S_IWUSR)) == -1)
|| ((shmaddr = shmat(shmid, NULL, 0)) == (char *)-1))
exit(0);
ptr = (struct set1 *)shmaddr;
ptr->id_number[0] = getpid();
/* ↓ 手抜きです m(_ _)m */
sprintf(command_line, "./xyz2 %d >>%s &", CODE, OUT_FILE);
if (system(command_line) != 0)
exit(0);
signal(SIGCONT, no_ope); /* シグナルハンドラー登録 */
while (1) {
write(STDERR, "> ", 2);
if ((nread = read(0, ptr->buffer, MEM_SIZE)) == -1)
exit(0);
if (ptr->buffer[0] == '!') {
ptr->flag[OUTPUT] = ON;
kill(ptr->id_number[OUTPUT], SIGCONT);
break;
} else {
ptr->flag[OUTPUT] = OFF;
ptr->buffer[nread - 1] = '\n';
ptr->buffer[nread] = '\0';
kill(ptr->id_number[OUTPUT], SIGCONT);
// ←に、出力プログラムを書く
pause(); // 子プロセスの出力完了まで待機
}
}
if (shmdt(shmaddr) == -1)
exit(0);
return 0;
}
void no_ope(int dummy) /* 何もしないシグナル処理関数 */
{
;
}
*-------------- ここまで ------------
/* xyz2.c parallel processing test program by gcc on Mac OSX
* execution: 並列出力専用ですから、シェルプロンプトから起動しないこと。
* compile: gcc xyz2.c -o xyz2
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <signal.h>
#define MEM_SIZE 256 /* xyz.c に合わせる */
#define PROCS 3
#define CODE 999
#define MY_ID 1
#define ON 1
#define OFF 0
#define PARENT 0
struct set1 {
char buffer[MEM_SIZE]; /* data buffer */
signed char flag[PROCS]; /* condtion flag */
pid_t id_number[PROCS]; /* id code */
} *ptr;
int shmid;
char *shmaddr;
void no_ope(int);
int main(int argc, char *argv[]) {
int temp_code;
/* 親プロセスから受け継ぐことにしました */
temp_code = atoi(argv[--argc]);
if (((shmid = shmget(temp_code, MEM_SIZE + sizeof(*ptr),
IPC_CREAT | S_IRUSR | S_IWUSR)) == -1)
|| ((shmaddr = shmat(shmid, NULL, 0)) == (char *)-1))
exit(0);
/* 前処理 */
ptr = (struct set1 *)shmaddr;
ptr->id_number[MY_ID] = getpid();
ptr->flag[MY_ID] = OFF;
signal(SIGCONT, no_ope);
while (1) {
pause(); // 親プロセスからのシグナルを待つ
if (ptr->flag[MY_ID] != OFF) {
kill(ptr->id_number[PARENT], SIGCONT);
break;
} else {
printf("%s", ptr->buffer);
kill(ptr->id_number[PARENT], SIGCONT);
}
}
if (shmdt(shmaddr) == -1)
exit(0);
return 0;
}
void no_ope(int dummy)
{
;
}
No.2
- 回答日時:
「2つのプロセスが同時に同じ共有メモリにアクセスすることは可能ですか?」との質問ですから、今話題のマルチコアあるいはメニーコアで行われるべき task parallelism(タスク並列)の問題ですよね。
結論からいえば可能です。ただし、これは米国特許事項であり、日本ではスパコンの話題が示すように認めたくない人が多いようです。それは the virtual programming language F によれば以下のように記述されます。書式はほぼCと同じですから、内容は理解できると思います。
プログラムはメインプログラムを主体に起動しますが、デーモン風にHDDに共有メモリの内容を書き出す send_hdd と terminal に出力する print_out プログラム、および万一に備え dead_lock 監視のフォールトトレラント機能を実現する dead_lock プログラムを並列起動して起きます。
各プログラムは、起動したならば自身のプロセスId を $buffer に示された struct 構造体で示される所定欄に書き込みます。その他、処理に必要な情報を書き込み、プログラム本体の処理に移ります。
1~3のデーモンプログラムは、補助的プログラムであるため通常は sleep するようにしますが、1の dead_lock はプロセス状態の監視用であるため、2~4の稼働状況をチェックしては 0.1~1秒間隔程度の sleep を繰り返します。
メインプログラムにおいて、shared memory の出力があるとき、signal を1~3のプロセスに送り、プロセスを wakeup させて同時に実行させることが出来ます。ただし、shared memory への書き込みに際しては2,3の動きに制約を設けなければなりません(セマフォなど)。
$buffer[] に格納される struct 構造体は、例えば my_job.h ヘッダーファイルとして定義しておき、各プログラムから #include “my_job.h” と宣言することで異プログラムながら同一プログラム感覚でプログラミングできるのです。
これら各プログラムの作成は、今使っているC言語を使い、更なる言語習得は不要です。このプログラム例から、下のプログラムは task parallelism を実現したものであるのがわかっていただけると思います。
これを使うことの利点は、shared memory をどうしようかと悩むことなく、Cプログラミングに集中できることです。
/* Sample program by the virtual programming language F.
* file name: parallel_computing
* execution: func "parallel_computing()" -m=17G
*/
shared /* Set global variable of shared memory */
$buffer[16G]; /* Keep buffer size 16G bytes */
%main($void) {
dead_lock $buffer & // 1. dead lock を監視、制御する
send_hdd $buffer & // 2. HDDに共有メモリを書き出す
print_out $buffer & // 3. terminal に出力する
main_prgm $buffer // 4. メイン・プログラム
/* return は不要である。*/
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
これ何て呼びますか Part2
あなたのお住いの地域で、これ、何て呼びますか?
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
スレッドにて同一メモリの書き込み、読み取り
C言語・C++・C#
-
共有メモリについて
C言語・C++・C#
-
<unistd.h>をVisualStudioでつかえるようにする
C言語・C++・C#
-
-
4
複数の共有メモリの作成
C言語・C++・C#
-
5
バッファとは何ですか
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
バックグラウンドのプロセスの...
-
explorer.exeが異様にメモリを食う
-
SendMessageが失敗するときがある
-
C#でのbatファイル実行結果取得
-
別のプロセスの関数を呼び出す...
-
プロセスのアタッチ・デタッチ...
-
CGIからCGIを、CGI環境変数付き...
-
タスクマネージャの「プロセス...
-
WSH.Runで待機できません
-
DLLにおいて、最後のプロセスデ...
-
VC++6.0 「プロセスへ...
-
ロードアベレージが高いのです...
-
ウィンドウのタイトルからプロ...
-
起動中のEXCELファイル(EXCEL...
-
Visual C++からpingを実行して...
-
共有メモリの同時アクセスにつ...
-
VB.NET 自プログラムのプロセス...
-
セマフォとmutexの違いは?
-
AppActivate関数について
-
警告『 別のプロセスで使用され...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
バックグラウンドのプロセスの...
-
タスクマネージャーのプロセス...
-
explorer.exeが異様にメモリを食う
-
プロセスのアタッチ・デタッチ...
-
C#でのbatファイル実行結果取得
-
プロセスIDからウィンドウハ...
-
VB6.0 SHELLで起動...
-
非表示になったエクセルは?
-
SendMessageが失敗するときがある
-
ADOでアクセスのレコードに...
-
c言語でプロセスIDを調べたい
-
Process.Startの戻り値を後で取得
-
OSPFでプロセスを分ける意義に...
-
セマフォとmutexの違いは?
-
Visual C++からpingを実行して...
-
プロセスIDの取得方法について
-
Linuxでのスレッド間メッセージ...
-
怪しいプロセス教えてください。
-
ウィンドウのタイトルからプロ...
-
別のプロセスの関数を呼び出す...
おすすめ情報