virtualization_processes.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. 1. Write a program that calls fork(). Before calling fork(), have the main
  3. process access a variable (e.g., x) and set its value to something (e.g., 100).
  4. What value is the variable in the child process?
  5. What happens to the variable when both the child and parent change the value of x?
  6. Answer:
  7. It has separate stack and heap and follow strategy COW which
  8. keep using parent pages
  9. 2. Write a program that opens a file (with the open() system call) and then calls
  10. fork() to create a new process. Can both the child and parent access the
  11. file descriptor returned by open()? What happens when they are writing to
  12. the file concurrently, i.e., at the same time?
  13. Answer:
  14. Since Kernel 3.14 this problem was fixed they can access now concurrently
  15. 3. Write another program using fork(). The child process should print “hello”;
  16. the parent process should print “goodbye”. You should try to ensure that the
  17. child process always prints first; can you do this without calling wait() in the parent?
  18. Answer:
  19. probably no
  20. 4. Write a program that calls fork() and then calls some form of exec()
  21. to run the program /bin/ls. See if you can try all of the variants of exec(),
  22. including (on Linux) execl(), execle(), execlp(), execv(), execvp(), and execvpe().
  23. Why do you think there are so many variants of the same basic call?
  24. Answer:
  25. who knows :P
  26. 5. Now write a program that uses wait() to wait for the child process
  27. to finish in the parent. What does wait() return? What happens if you use wait() in the child?
  28. Answer:
  29. wait for the child process -> no child processes error
  30. 6. Write a slight modification of the previous program, this time using
  31. waitpid() instead of wait(). When would waitpid() be useful?
  32. Answer:
  33. When we want to control which child state changes we are waiting for
  34. 7. Write a program that creates a child process, and then in the child
  35. closes standard output (STDOUT_FILENO). What happens if the child calls
  36. printf() to print some output after closing the descriptor?
  37. Answer:
  38. Simply it will not be printed
  39. 8. Write a program that creates two children, and connects the standard
  40. output of one to the standard input of the other, using the pipe() system call.
  41. */
  42. #define _GNU_SOURCE
  43. #include <sys/types.h>
  44. #include <sys/wait.h>
  45. #include <sys/stat.h>
  46. #include <fcntl.h>
  47. #include <unistd.h>
  48. #include <stdio.h>
  49. #include <string.h>
  50. #include <stdlib.h>
  51. static int x_global = 10;
  52. static const char *filename = "dummy";
  53. static const char *dummy_text = "hello baby";
  54. void program_8(void)
  55. {
  56. int pipefd[2];
  57. if (pipe(pipefd) == -1) {
  58. perror("pipe");
  59. exit(EXIT_FAILURE);
  60. }
  61. int rc;
  62. if ((rc = fork()) == 0) {
  63. close(pipefd[1]); /* close write */
  64. puts("child 1");
  65. char buffer[10];
  66. ssize_t bytes;
  67. while ((bytes = read(pipefd[0], buffer, 10)) > 0) {
  68. buffer[bytes] = '\0';
  69. printf("buffer: %s\n", buffer);
  70. }
  71. exit(EXIT_SUCCESS);
  72. }
  73. if ((rc = fork()) == 0) {
  74. puts("child 2");
  75. close(pipefd[0]); /* close read */
  76. write(pipefd[1], dummy_text, strlen(dummy_text));
  77. exit(EXIT_SUCCESS);
  78. }
  79. close(pipefd[0]);
  80. close(pipefd[1]);
  81. wait(NULL);
  82. }
  83. void program_7(void)
  84. {
  85. int rc = fork();
  86. if (rc == 0) {
  87. puts("child before closing");
  88. close(STDOUT_FILENO);
  89. puts("child after closing");
  90. } else if (rc > 0) {
  91. wait(NULL);
  92. } else {
  93. perror("fork failed\n");
  94. }
  95. }
  96. void program_5(void)
  97. {
  98. int rc = fork();
  99. if (rc == 0) {
  100. printf("hello\n");
  101. pid_t pid;
  102. if ((pid = waitpid(-1, NULL, WNOHANG)) == -1) {
  103. perror("wait failed");
  104. }
  105. } else if (rc > 0) {
  106. // wait(NULL);
  107. waitpid(-1, NULL, 0);
  108. printf("goodbye\n");
  109. } else {
  110. perror("fork failed\n");
  111. }
  112. }
  113. void program_4(void)
  114. {
  115. int rc = fork();
  116. if (rc == 0) {
  117. char **iter = environ;
  118. puts("print environment");
  119. while (*iter) {
  120. printf("%s\n", *iter);
  121. ++iter;
  122. }
  123. const char *envp[] = { "PATH=/bin:/usr/bin", NULL };
  124. // execl("/bin/ls", "ls", (char *)NULL);
  125. /* execute and search in PATH */
  126. // execlp("ls", "ls", (char *)NULL);
  127. /* specify environment variable of executed
  128. program but not change the actual PATH */
  129. /* execle("/bin/ls", "ls", (char *)NULL, envp); */
  130. /* execv use list instead of variadic parameter */
  131. execv("/bin/ls", (char*[]){"ls", NULL});
  132. } else if (rc > 0) {
  133. wait(NULL);
  134. printf("goodbye\n");
  135. } else {
  136. perror("fork failed\n");
  137. }
  138. }
  139. void program_3(void)
  140. {
  141. int rc = fork();
  142. if (rc == 0) {
  143. printf("hello\n");
  144. } else if (rc > 0) {
  145. wait(NULL);
  146. printf("goodbye\n");
  147. } else {
  148. perror("fork failed\n");
  149. }
  150. }
  151. void program_2(void)
  152. {
  153. int fd;
  154. if ((fd = open(filename,
  155. O_CREAT | O_TRUNC | O_WRONLY,
  156. S_IRUSR | S_IWUSR)) == -1) {
  157. perror("error occured");
  158. return;
  159. }
  160. int rc = fork();
  161. if (rc == 0) {
  162. write(fd, dummy_text, strlen(dummy_text));
  163. } else if (rc > 0) {
  164. write(fd, dummy_text, strlen(dummy_text));
  165. wait(NULL);
  166. } else {
  167. fprintf(stderr, "fork failed\n");
  168. }
  169. close(fd);
  170. }
  171. void program_1(void)
  172. {
  173. int x_local = 10;
  174. int rc = fork();
  175. if (rc == 0) {
  176. puts("In child process");
  177. printf("child x_local: %d\n", x_local);
  178. printf("parent x_global: %d\n", x_global);
  179. } else if (rc > 0) {
  180. x_local = 5;
  181. x_global = 5;
  182. printf("parent x_local: %d\n", x_local);
  183. printf("parent x_global: %d\n", x_global);
  184. puts("In parent process");
  185. printf("the child process %d was created\n", rc);
  186. int wstatus;
  187. rc = wait(&wstatus);
  188. printf("the child %d finished its work status: %d\n", rc, wstatus);
  189. } else {
  190. fprintf(stderr, "fork failed\n");
  191. }
  192. }
  193. int main(void)
  194. {
  195. program_8();
  196. return 0;
  197. }