質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
C

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

Linux

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

シェル

シェル(shell)はUnix や Linux 系のOSで使用されるコマンドインタプリタを指します。

Q&A

2回答

5862閲覧

C言語で自作シェル jobs,fgのコマンドの実行

kokuten5

総合スコア8

C

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

Linux

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

シェル

シェル(shell)はUnix や Linux 系のOSで使用されるコマンドインタプリタを指します。

0グッド

0クリップ

投稿2016/10/16 17:39

###前提・実現したいこと
C言語でLINUXの自作シェルの作成をしています。
今は jobs と fg を内部コマンドとして追加することをしていますがうまくいきません。
jobsではBG実行されているプロセス一覧を表示する。(jobsコマンド時に通し番号をつけて表示する)
fgではBG実行プロセスのうち、指定した一個をFGに切り替える。(fgコマンドではその番号を指定してFGに切り替える)
以上の二つを実現したいです。

###発生している問題・エラーメッセージ
今、何個のプロセスがBG実行されているのかの数え方が分かりません。
子プロセスのところでp_n++を使って子プロセスが実行された回数を調べようと思ったのですが、うまく数えることができないです。

###該当のソースコード
.#include <stdio.h>
.#include <stdlib.h> //exitを使うために取り込む
.#include <unistd.h> //execvとforkを使うために取り込み
.#include <string.h> //strtokとstrcmpを使うために取り込み
.#include <sys/wait.h> //waitpidを使うために取り込み

int main(void) {
pid_t pid; //プロセスの生成
char com[256]; //文字読み込み用
char *argv[256];
char *ptr; //ポインタ
int i; //ループ時のカウンタ
char *and; //文字列に&がなければNULL
char a = '&';
int status;
int p_n = 0; //プロセスの数を数える

//whileループ
while(1) {

//プロンプト表示 printf("prompt: "); //入力読み込み fgets(com, sizeof(com), stdin); //入力した文字列に&がついてるか判断 and = strchr(com, a); //argv1に上で読み込んだcomを代入 argv[0] = strtok(com, " \n\0"); //ループさせてポインタを動かす //strtokを使い空白とエンターで分解 //ポインタを使い分解したものを配列に入れていく for(i = 1; i < 256; i++) { ptr = strtok(NULL, " &\n\0"); argv[i] = ptr; //文字列が分解し終わったらループを抜け出す if (ptr == NULL) break; } //判断 exit quitなら終了 if(strcmp(com,"exit") == 0 || strcmp(com,"quit") == 0) exit(0); //分裂(fork) 新しいプロセスをつくる pid = fork(); //プロセス作成に失敗したときは、0未満を返す if(pid < 0) { printf("error\n"); exit(-1); } //親と子の判断 //子プロセス //子プロセス読み込んだコマンドを実行(execv) //exitで抜け出す if(pid == 0) { execv(argv[0], argv); p_n++; exit(0); } //親プロセス //andがNULLの時(&がない時) //親プロセス待機(子プロセス終了待ち) if(pid > 0) { if(and == NULL){ waitpid(pid, &status, 0); } } /*jobs 稼働状況の表示(ループ) [通し番号] プロセス名*/ printf(" %d\n",p_n); for(i = 0; i < 0; i++){ //通し番号 printf("[%d] ", i); //ジョブ名(ファイル名) printf("%s \n", com); } //一つに戻り再開(ループ)

}
return 0;
}

###最後に
どなたかわかる方教えていただけたらありがたいです。

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

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

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

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

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

moonphase

2016/10/17 00:12

コードは上下を ``` で囲むと見やすくなります。
guest

回答2

0

以下の子プロセスで、execv()が成功した時点で、その後のコードは実行されません。
execv()が失敗してp_nが子プロセスでインクリメントされても、そのままexit(0)しているので意味がありません。
親プロセスが子プロセスの起動数を管理してください。

if (pid == 0) { execv(argv[0], argv); p_n++; exit(0); }

投稿2016/10/17 00:15

編集2016/10/17 00:26
moonphase

総合スコア6621

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

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

mit0223

2016/10/17 00:24

あ、 execv に失敗したときの話に言及するのを忘れてました。私の「永遠に実行されない」は嘘でしたね。
guest

0

子プロセスで execv を実行すると、プロセス自身が呼び出すプログラムに置き換わるので、 execv の後ろに何を書いても無効です。具体的には、

c

1p_n++; 2exit(0);

の2行は永遠に実行されることはありません。p_n++ は親プロセスで実行する必要があります。


moonphaseさんの回答を見て気づきました。execv に失敗する場合もあるので、上記の「永遠に実行されることはありません」は嘘でした。自作シェルとのことですので、エラーを印刷して exit(1) するなど、エラー処理を書くべきですね。

投稿2016/10/17 00:09

編集2016/10/17 00:28
mit0223

総合スコア3401

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問