🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

排他制御

排他制御とは、特定のファイル・データへのアクセスや更新を制御することです。特にファイルやデータベースへ書き込みを行う際、データの整合性を保つため別のプログラムによる書き込みを一時的に制御することを指します。

セマフォ

セマフォは、並行プログラミングにおいて同期のサポートを行うための機構。また、それによりプロセス間で交換される信号を指します。複数のプロセスでファイルなどを共有している際の同時アクセスによる破壊や不整合を防ぐことが可能です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Q&A

1回答

1363閲覧

Linux環境でのセマフォ処理

Timosy

総合スコア3

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

排他制御

排他制御とは、特定のファイル・データへのアクセスや更新を制御することです。特にファイルやデータベースへ書き込みを行う際、データの整合性を保つため別のプログラムによる書き込みを一時的に制御することを指します。

セマフォ

セマフォは、並行プログラミングにおいて同期のサポートを行うための機構。また、それによりプロセス間で交換される信号を指します。複数のプロセスでファイルなどを共有している際の同時アクセスによる破壊や不整合を防ぐことが可能です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

1グッド

2クリップ

投稿2021/01/15 07:11

#質問

Linux環境において2つのプログラム(プロセス)を用いてデータを送り,それを受信するというプログラムを書きました.
ですが「送信者が立て続けにメッセージを送信すると,受信者が受信に失敗する場合」や「送信者がしばらくメッセージを送信しない場合,受信者が同じメッセージを何度も受信してしまう場合」などがあります.
セマフォを使えばよいとのアドバイスを受けたのですがどうすればよいか分かりません.
どなたかコーディングを教えていただけないでしょうか.

#試したこと

以下は実際に作成したプログラム(セマフォによる排他制御は行っていないもの)です.

##send_by_shm.c

C

1#include <stdio.h> 2#include <sys/types.h> 3#include <sys/ipc.h> 4#include <sys/shm.h> 5#include <stdlib.h> 6#include <string.h> 7 8int main (int argc, char *argv[]) 9{ 10 int id; 11 char *adr; 12 13 if (argc !=2) 14 { 15 fprintf(stderr, "Usage: send-by-shm <Shared memory ID>"); 16 exit (EXIT_FAILURE); 17 } 18 19 id=atoi(argv[1]); 20 if((int) (adr = (char *)shmat (id, (void *) 0, 0)) == -1) 21 { 22 perror("shmat"); 23 exit(EXIT_FAILURE); 24 } 25 else 26 { 27 while(1) 28 { 29 printf("Input any string>"); 30 fgets(adr, 512, stdin); 31 adr[strlen(adr)-1] = '\0'; 32 if(strcmp (adr, "quit") == 0) 33 break; 34 } 35 if (shmdt (adr) == -1) 36 { 37 perror("shmdt"); 38 exit (EXIT_FAILURE); 39 } 40 } 41} 42

##receive_by_shm.c

C

1#include <stdio.h> 2#include <sys/types.h> 3#include <sys/ipc.h> 4#include <sys/shm.h> 5#include <stdlib.h> 6#include <string.h> 7 8#define BUFSIZE 512 9 10int main() 11{ 12 int id; 13 char *adr; 14 15 if ((id = shmget (IPC_PRIVATE, BUFSIZE, IPC_CREAT|0666)) == -1) 16 { 17 perror ("shmget"); 18 exit(EXIT_FAILURE); 19 } 20 printf("Shared memory ID =%d\n", id); 21 22 if ((int)(adr=(char *) shmat (id, (void *) 0, 0)) == -1) 23 { 24 perror ("shmat"); 25 shmctl(id, IPC_RMID, NULL); 26 exit (EXIT_FAILURE); 27 } 28 else 29 { 30 strcpy (adr, "Initial"); 31 while(1) 32 { 33 printf("%s\n", adr); 34 if (strcmp (adr, "quit") == 0) { 35 break; 36 } 37 sleep(3); 38 } 39 40 if (shmdt (adr) == -1) 41 { 42 perror("shmdt"); 43 shmctl(id, IPC_RMID, NULL); 44 exit (EXIT_FAILURE); 45 } 46 } 47 48 if(shmctl(id, IPC_RMID, NULL) == -1) 49 { 50 perror("chmctl"); 51 exit(EXIT_FAILURE); 52 } 53}

#実行結果

一度でいいメッセージを何度も受信してしまっている状況です.

Shared memory ID = 753669 Initial Initial Initial Initial Initial Initial Initial Initial Initial ...
A_kirisaki👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2021/01/15 07:28

先の質問が解決していないとセマフォを正しく扱えないと思うのですがいかがでしょうか。 [Linux環境下のでセマフォ] https://teratail.com/questions/315825 それができた前提で、本質問では共有メモリを使っているので、「メモリに空きがあれば(読み出し済みであれば)書く。これが言うなればsend」、「メモリが埋まっていれば(書き込み済みであれば)読む。これが言うなればreceive」で、その排他制御にセマフォを使うようなかたちになるかと思います。
guest

回答1

0

「送信者が立て続けにメッセージを送信すると,受信者が受信に失敗する場合」や「送信者がしばらくメッセージを送信しない場合,受信者が同じメッセージを何度も受信してしまう場合」など

排他は読んで字の通り、他を排して、一つのリソースを扱うのが常にひとつのタスクであるようにすることです。
しかし、いずれの現象も、排他処理の話でもないし解決手段はセマフォではないでしょう。

現象に対する解決は「ハンドシェイク」でいいのかな、

  • データを用意する側はデータを設定したら「データあり」フラグを立てる
  • 受け取る側は「データあり」フラグを見ていて、フラグが立ったらデータを取得して、「データあり」フラグをクリアする
  • データを用意する側は、「データあり」フラグが立っていないことを確認して、次のデータを設定し、「データあり」フラグを立てる

とでもするのでしょう(フラグの領域には共有メモリの先頭1バイトを割り当てるとか)。この場合であれば、フラグに対してもデータに対しても競合は発生しませんから、排他は(セマフォも)必要ありません。

投稿2021/01/15 22:28

thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2021/01/15 23:30

質問者さんの先の質問の流れで、排他制御の勉強も含め、あくまでセマフォなど使って解決したいのかな、と思いました。ですが、問題の解決を優先するとするとロジックで解決できますね。 ※ちなみにこちらの質問と同等のようです。 [共有メモリを使ったメッセージの送信]https://teratail.com/questions/316279
thkana

2021/01/16 01:21

過去質問、見た記憶はあるけど十分な回答が付いてるからいいや、と流したんだっけ。 排他制御が不要なお題で排他制御の勉強をしようとしても、ねぇ。 > セマフォを使えばよいとのアドバイス をした人を問い詰めてみたい気分です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問