I'm trying to execute and schedule my own list of processes read from a file. The files are running in a random order and I'm just curious as to why this is happening. I have simple print statements in the first, second, etc files that tell which is running, and they always print in different (seemingly random) orders. It isn't messing up my functionality thus far, I'm just curious why this is.
main.c below
int main(int argc, char ** argv) {
pid_t pid[50];
pid_t wpid;
int i, j;
int status = 0;
char *newenvp[] = {NULL};
char *newargv[] = {"./files.txt", NULL};
printf("Before forking in the parent\n");
int numProgs = readPrograms();
for (i=0; i<numProgs; i++) {
pid[i] = fork();
if (pid[i] < 0) {
perror("fork error");
exit(EXIT_FAILURE);
}
else if (pid[i] == 0) {
printf("Child process running\n");
execve(programs[i], newargv, newenvp);
perror("execve error");
exit(EXIT_FAILURE);
}
}
for (i=0; i<numProgs; i++) {
wait(&status);
}
return 0;
}
char* programs[50];
int readPrograms();
readPrograms.c below
int readPrograms() {
int i=0;
char line[50];
int numProgs = -1;
FILE *file;
file = fopen("files.txt", "r");
while(fgets(line, sizeof(line), file)!=NULL) {
line[strlen(line)-1] = '\0';
programs[i]=strdup(line);
i++;
numProgs++;
}
fclose(file);
return numProgs;
}
files.txt below
./first
./second
./third
./fourth
When calling fork, your system creates the new process (copy itself,call exec,overlay itself).
Then your fork is ready, both the parent and the child process are marked ready and the running order of the processes is chosen by your system-scheduler.
So depending on your scheduler either your parent or your child is now run.
Related
This is the main in test1.c:
int main(int argc, char *argv[])
{
int fd1,i, *foo;
pid_t childpid;
mkfifo("myfifo1", 0777);
foo = malloc(10*sizeof(int));
childpid=fork();
if (childpid== -1){
perror("Failed to fork\n");
exit(1);
}
if (childpid==0) {
execlp(argv[1],argv[1],(char *) NULL);
perror("exec failure ");
exit(1);
}
else {
wait(NULL);
fd1 = open("myfifo1", O_RDONLY, 0);
for (i=0; i<10; i++) {
read(fd1, &foo[i], sizeof(int));
}
for (i=0; i<10; i++) {
printf("%d\n", foo[i]);
}
}
close(fd1);
}
and this is the main in test2.c:
int main(int argc, char *argv[])
{
int fd1, i, *foo;
fd1 = open("myfifo1", O_WRONLY);
if (fd1==-1) printf("error\n");
foo = malloc(10*sizeof(int));
for (i=0; i<10; i++) {
write(fd1, &i, sizeof(int));
}
printf("\n");
close(fd1);
}
When I run ./test1 ./test2 the program hangs. I assume that this happens because in test2.c only one end of the pipe opens and the program waits for the other one to do so. However, this never happens because of:
wait(NULL)
And indeed if I remove this command the program works fine. However, I thought that wait is always useful and it is prevents us from creating zombie processes. Am I wrong at all these? Is there any way to keep the wait command and make the program work?
Thanks in advance!
I was given this particular task:
Using SIGCONT, SIGSTOP, and SIGCHLD, write a program that accepts
through argv[] a list of commands (none of them has arguments) and
runs the commands in a round-robin style, alternating commands in
1-second intervals.
To achieve it, I tried this:
int dead_children = 0;
int nr_processes;
void inc_dead () {
printf("I, %d, died\n", getpid());
dead_children++;
if (dead_children == nr_processes)
_exit(0);
}
int main (int argc, char *argv[]) {
int pids[argc - 1];
nr_processes = argc - 1;
signal(SIGCHLD, inc_dead);
for (int i = 1; i < argc; i++) {
pid_t pid;
if ( (pid = fork()) == -1 ) {
perror("fork");
return EXIT_FAILURE;
}
if ( !pid ) {
pause();
execlp(argv[i], argv[i], (char *) NULL);
perror("exec");
_exit(1);
}
pids[i - 1] = pid;
}
while (dead_children < nr_processes)
for (int j = 0; j < argc - 1; j++) {
kill(pids[j], SIGCONT);
sleep(1);
kill(pids[j], SIGSTOP);
}
return EXIT_SUCCESS;
}
I tried to run this code with very simple program that would allow me to verify task's correctness:
int main (void) {
int i = 5;
while (i-- > 0) {
printf("This is %d saying HI!\n", getpid());
sleep(1);
}
return EXIT_SUCCESS;
}
However, this does not work. I noticed that after creation, child processes never left pause() instruction, even though parent is sending a SIGCONT. Any thoughts on how to achieve the goal?
I am trying to communicate with children processes and make them sort a part of a list. My problem is children processes read everything but do nothing after it.
int main(int argc, char *argv[]){
int i;
int num_children;
pid_t pid;
num_children= 3;
int fd[num_children][2]; //PIPES
for (i=0; i<num_children; i++)
{
if (pipe(fd[i]) == -1)
{
printf("couldnt create the pipe\n");
exit(EXIT_FAILURE);
}
}
for (i=0; i<num_children; i++)
{
pid = fork();
if (pid == -1)
{
printf("couldnt create child process %i\n",i);
exit(EXIT_FAILURE);
}
if (pid == 0)
{ //this is child process
close(fd[i][1]); //closing fd[1] the write end of the pipe
int received;
node *list = NULL;
while ( read(fd[i][0], &received, sizeof(int)) > 0)
{
list = insert(list, received);
printf("Process %i got the number: %i\n",i,received); //this part is working perfect
}
printf("Im process %i here is my list: \n",i); //i couldnt get any output from here
printList(list);
close(fd[i][0]);
exit(EXIT_SUCCESS);
}
}
for (i=0; i<num_children; i++) //closing the read end of pipe for parent
{
close(fd[i][0]);
}
int number;
int mod;
FILE *fileIn = fopen ("<file directory>","r");
while(fscanf(fileIn, "%i", &number)>=0)
{
mod = number % num_children;
write(fd[mod][1], &number, sizeof(int));
}
for (int i=0; i<num_children; i++)
{
if(close(fd[i][1])==0)
{
printf("cant close the pipe");
//tried to catch errors, but pipes are closing with no problem i think
}
}
return 0;
I tried to see if children process wait in the while(read) loop, but when i close the write end of pipes from the parent process they should leave the loop.
You're probably thinking that some specific pipe[2] is shared by the parent and it's respective child process. That's true ... However it is also shared by all the other children processes you create along the way - and because it's opened, those other children processes also inherit it as opened.
Doing this at the beginning of your child pid check worked for me:
if (pid == 0) {
int j;
for (j = 0; j < num_children; j++) {
if (j != i) {
close(fd[j][0]);
close(fd[j][1]);
}
}
...
}
I suspect that the reading from the pipe via:
while ( read(fd[i][0], &received, sizeof(int)) > 0)
is being blocked/haulted until data is available on the pipe. If so, this would explain the lack of response from your code after this point.
I'm trying to write a program to execute and schedule a list of processes. My code for main.c is below. When run, I receive an error from perror saying there is no such file or directory. I'm guessing this is because the files/programs in my files.txt are not binary executables but I'm not sure how to fix this. files.txt contains the list of programs I want to run. They have all been converted to binary executables already. programs is an array containing the four programs that have been read by the readPrograms function
int main(int argc, char ** argv) {
pid_t pid[50];
pid_t wpid;
int i, j;
int status = 0;
char *newenvp[] = {NULL};
char *newargv[] = {"./files.txt", NULL};
printf("Before forking in the parent\n");
int numProgs = readPrograms();
for (i=0; i<numProgs; i++) {
pid[i] = fork();
if (pid[i] < 0) {
perror("fork error");
exit(EXIT_FAILURE);
}
else if (pid[i] == 0) {
printf("Child process running\n");
execve(programs[i], newargv, newenvp);
perror("execve error");
exit(EXIT_FAILURE);
}
}
for (i=0; i<numProgs; i++) {
wait(&status);
}
return 0;
}
char* programs[50];
int readPrograms();
files.txt below
./first
./second
./third
./fourth
(I did "cc first.c -o first" for all of these files respectively)
I suspect the bug is in the code you're not showing, readPrograms. Most likely you're reading the lines of the text file with fgets and each string has a newline on the end of it, whereas your filenames don't have newlines in them.
I am given the task of forking n processes.
For each process, it must start an instance of /bin/xterm
I am done with the part of generating n processes and opening the xterm instance.
I got this output when I tried running the program. (Error in bold)
Number of process to open is 1.
Child (1): 3457
/bin/xterm: Xt error: Can't open display:
/bin/xterm: DISPLAY is not set
My code is below.
I tried googleing for the error but I have no luck so far.
Any solutions?
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
int num = atoi(argv[1]);
printf("Number of process to open is %d.\n", num);
int pid;
int i;
for(i = 0; i < num; i++)
{
pid = fork();
if(pid < 0) {
printf("Error");
exit(1);
} else if (pid == 0) {
printf("Child (%d): %d\n", i + 1, getpid());
char * const argv[] = {"/bin/xterm", NULL};
char * const envp[] = {NULL};
int rc = execve ("/bin/xterm", argv, envp);
exit(0);
} else {
wait(NULL);
}
}
return 0;
}
This little changed code works perfectly fine on my system:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(int argc, char *argv[])
{
int num = atoi(argv[1]);
printf("Number of process to open is %d.\n", num);
int pid;
int i;
for(i = 0; i < num; i++)
{
pid = fork();
if(pid < 0) {
printf("Error");
exit(1);
} else if (pid == 0) {
//printf("Child (%d): %d\n", i + 1, getpid());
//char * const argv[] = {"/bin/xterm", NULL};
//char * const envp[] = {NULL};
execl("/usr/bin/xterm", "/usr/bin/xterm", NULL);
//exit(0);
}else {
wait(NULL);
}
}
return 0;
}
The error was explained in the output you pasted:
/bin/xterm: DISPLAY is not set
You need to set DISPLAY appropriately. Otherwise, it will have no way to know where to put its display.
Also, did you really want to wait for each child after creating it?
Use
char *envp[] = {"TERM=vt100", "PATH=/bin:/usr/bin", "DISPLAY=:0.0",(char *) 0 };
Doing so you set the display on your machine.
Sorry I'm late.