私は現在オペレーティングシステムと並行性を研究していますが、プロセススケジューラに関する私のプラクティスの1つは、Linuxで複数のプロセスがどのように「並列」で動作するかをC言語で把握し、ここに私のコードは次のとおりです。LinuxのCでfork()によって生成された子プロセスのシェルでの出力リダイレクトはどのように機能しますか?
/* This file's name is Task05_3.c */
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
int kill(pid_t pid, int sig);
unsigned usleep(unsigned seconds);
#define NUMBER_OF_PROCESSES 7
#define MAX_EXPERIMENT_DURATION 4
long int getDifferenceInMilliSeconds(struct timeval start, struct timeval end)
{
int seconds = end.tv_sec - start.tv_sec;
int useconds = end.tv_usec - start.tv_usec;
int mtime = (seconds * 1000 + useconds/1000);
return mtime;
}
int main(int argc, char const *argv[])
{
struct timeval startTime, currentTime;
int diff;
int log[MAX_EXPERIMENT_DURATION + 2] = {-1};
/* initialization */
for (int k = 0; k < MAX_EXPERIMENT_DURATION + 2; ++k)
log[k] = -1;
gettimeofday(&startTime, NULL);
pid_t pid_for_diss = 0;
for (int i = 0; i < NUMBER_OF_PROCESSES; ++i)
{
pid_for_diss = fork();
if (pid_for_diss < 0) {
printf("fork error, errno(%d): %s\n", errno, strerror(errno));
} else if (pid_for_diss == 0) {
/* This loop is for logging when the child process is running */
while (1) {
gettimeofday(¤tTime, NULL);
diff = getDifferenceInMilliSeconds(startTime, currentTime);
if (diff > MAX_EXPERIMENT_DURATION)
{
break;
}
log[diff] = i;
}
// for (int k = 0; k < MAX_EXPERIMENT_DURATION + 2; ++k)
// {
// if (log[k] != -1)
// {
// printf("%d, %d\n", log[k], k);
// }
// }
// exit(0);
break;
}
}
/* This loop is for print the logged results out */
if (pid_for_diss == 0)
{
for (int k = 0; k < MAX_EXPERIMENT_DURATION + 2; ++k)
{
if (log[k] != -1)
{
printf("%d, %d\n", log[k], k);
}
}
kill(getpid(), SIGKILL);
}
int status;
while (wait(&status) != -1);// -1 means wait() failed
printf("Bye from the parent!\n");
}
は基本的に、ここでの私の考えでは(私はフォークで7つのプロセスを生成するために、親プロセスのループのために設定されていることである)とを競うためにそれらを強制whileループにそれらを設定しますある期間内のCPUの使用。そして、子プロセスが実行されるようにスケジュールされるたびに、現在の時間と親プロセスの開始時間との差を、実行中の子プロセスに属するアレイに記録します。それから、7つのプロセスがすべてwhileループを壊した後、私はそれぞれの子プロセスが別のループを設定して、ログに記録された結果を表示します。 最初に、forループの外側に印刷するためのループを設定しました(私のコードでわかるように) 、と私はbashで直接./Task05_3
を実行し、ここでの結果である:
[email protected]:osc$ gcc -std=c99 Task05_3.c -o Task05_3
[email protected]:osc$ ./Task05_3
5, 0
4, 0
6, 0
4, 1
1, 0
4, 2
4, 3
4, 4
0, 0
1, 1
6, 1
1, 2
1, 3
1, 4
5, 1
5, 2
5, 3
5, 4
6, 2
6, 3
2, 0
6, 4
2, 1
2, 2
2, 3
2, 4
0, 1
3, 0
0, 2
0, 3
0, 4
3, 1
3, 2
3, 3
3, 4
Bye from the parent!
[email protected]:osc$
あなたは(親プロセスと子プロセスの両方から)すべての結果は、端末との結果にプリントアウトされていることをここで見ることができます子プロセスはランダムな順序になっています(これは、同時に複数のプロセスが標準出力に書き込むことが原因と考えられます)。しかし、./Task05_3 > 5output_c.csv
で実行しようとすると、私のターゲットとなる.csvファイルには、親プロセスからの結果しか含まれていないことがわかります。Result_in_csv01
私の最初の質問は、どのように.csvファイル親プロセスのプロンプトが含まれていますか?それは、私がbashでタイプした命令は、親プロセスの出力をリダイレクトするだけで、子プロセスの出力ストリームとは何の関係もないからですか?
メジャーなforループの中にforループ(印刷用)を入れようとすると(上記のコードのforループを参照してください)、./Task05_3 > 5output_c.csv
でコードを実行すると、ファイルは次のようになります:Result_in_csv02
これですべての結果が表示されます!子プロセスの結果の順序は、もはやランダムではありません! (実行中の子プロセスがすべての結果を出力するまで、他の子プロセスは明らかに待機しています)。だから私の2番目の質問は、私が単に私のforループの位置を変更した後にこれがどうして起こるかということです。
PS。私はあるに私のコードを実行したLinuxマシン:
[email protected]:osc$ cat /proc/version
Linux version 3.10.0-693.2.2.el7.x86_64 ([email protected]) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC)) #1 SMP Tue Sep 12 22:26:13 UTC 2017
そして、GCCのバージョンは次のとおりです。
[email protected]:osc$ gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
お返事と説明してくれてありがとう、それは本当にはっきりと便利です。ちなみに、私はまだ私の子プロセスの出力が、ファイルバッファに格納された状態で端末にランダムに印刷されているため、ファイルにリダイレクトしたとき(ブロックバッファの場合、あなたが言ったように)もう少し具体的に説明できますか? Thx again〜 – TyBcodar
@TyBcodar 2番目のバージョンでは、(exit(0) '呼び出しの一環として)各子に1つのアトミック' write() 'しか実行されないので、1つのプロセスのすべての出力一度に一緒に出現する。最初のバージョンでは、すべてのプロセスのすべての行が、すぐに独立して書き込まれます。 – melpomene