我目前正在研究操作系统和并发性,有关进程调度程序的一种实践是使用C语言来计算多个进程如何在Linux中以“毫秒”粒度“并行”工作。 这是我的代码:
/* This file's name is Task05_3.c */
#include
#include
#include
#include
#include
#include
#include
#include
#include
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");
}
基本上,我的想法是为父进程设置一个for循环,以使用fork()产生7个子进程,并将它们设置为while循环,以迫使它们在一段时间内竞争CPU的使用。 并且每次安排子进程运行时,我大约将当前时间与父进程的开始时间之间的差记录到属于正在运行的子进程的数组中。 然后,在所有7个进程都打破了while循环之后,我为每个子进程设置了另一个for循环以打印出其记录的结果。
但是,当我尝试将输出重定向到Linux机器中的.csv文件时,发生了一些奇怪的事情:首先,我将循环设置为在主for循环之外进行打印(如您在代码中所见),然后运行./Task05_3直接放在bash中,结果如下:
psyhq@bann:osc$ gcc -std=c99 Task05_3.c -o Task05_3
psyhq@bann: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!
psyhq@bann:osc$
您可以在此处看到所有结果(来自父过程和子过程)都已在终端中打印出来,并且子过程的结果是随机顺序的(我认为这可能是由于多个过程写入了标准输出)与此同时)。 但是,如果尝试通过./Task05_3 > 5output_c.csv运行它,我会发现我的目标.csv文件仅包含来自父进程的结果,它看起来像: Result_in_csv01
所以我的第一个问题是.csv文件如何仅包含父进程的提示? 是因为我在bash中键入的指令仅重定向了父进程的输出,而与子进程的输出流无关?
而且,当我尝试将for循环(用于打印)放入主for循环(请参阅上面我的代码中注释的for循环)并通过./Task05_3 > 5output_c.csv运行代码时,发生了更令人困惑的事情, .csv文件现在看起来像: Result_in_csv02
现在它包含所有结果! 子进程结果的顺序不再是随机的! (显然,其他子进程一直等待,直到正在运行的子进程将其所有结果打印出来)。 因此,我的第二个问题是,仅更改了for循环的位置后怎么办?
PS。 我运行代码的Linux机器位于:
psyhq@bann:osc$ cat /proc/version
Linux version 3.10.0-693.2.2.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC) ) #1 SMP Tue Sep 12 22:26:13 UTC 2017
GCC版本是:
psyhq@bann: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.