System calls 是由 user program 要執行 privileged operations (e.g. I/O) 需切換到 kernel mode 的操作。
Traps 是 CPU 層面的 error 導致要切換到 kernel mode 的操作。
舉例來說,當行程 A forks B 時,如果 B 執行了 exec() 那麼行程 B 的 stack 和 address space 都會被 新的執行程式覆蓋,所以不會 return。
在研讀 OSTEP - Process API 時,有一段程式碼如下方。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
printf("hello world (pid:%d)\n", (int) getpid());
int rc = fork();
if (rc < 0) {
// fork failed; exit
fprintf(stderr, "fork failed\n");
exit(1);
} else if (rc == 0) {
// child (new process)
printf("hello, I am child (pid:%d)\n", (int) getpid());
} else {
// parent goes down this path (original process)
printf("hello, I am parent of %d (pid:%d)\n",
rc, (int) getpid());
}
return 0;
}
在使用 $ ./p1
去執行的結果如下:
hello world (pid:79862)
hello, I am parent of 79863 (pid:79862)
hello, I am child (pid:79863)
在使用 $ watch -n 1 ./p1
去執行的結果如下:
Every 1.0s: ./p1
hello world (pid:80079)
hello, I am parent of 80080 (pid:80079)
hello world (pid:80079)
hello, I am child (pid:80080)
為什麼會發生這樣的情況呢?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
int p1 = fork();
if (p1 < 0) {
fprintf(stderr, "fork failed\n");
exit(EXIT_FAILURE);
} else if (p1 == 0) {
execl("/bin/ls", "", "-la", (char*) NULL); // why we need an extra "" as argument?
} else {
wait(NULL);
}
return EXIT_SUCCESS;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void) {
pid_t p_pid = getpid();
printf("Parent PID: %d\n", p_pid);
int fork_rc = fork();
if (fork_rc < 0) {
fprintf(stderr, "fork failed.");
exit(EXIT_FAILURE);
} else if (fork_rc == 0) {
printf("Child PID: %d\n", (int) getpid());
waitpid(p_pid, NULL, 0);
} else {
int wait_rc = waitpid(fork_rc, NULL, 0);
printf("wait_rc: %d\n", wait_rc);
}
return EXIT_SUCCESS;
}
stderr
is unbuffered-1 Bad file descriptor
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(void) {
int pipefd[2];
char* buf;
pid_t cpid1;
pid_t cpid2;
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid1 = fork();
if (cpid1 == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (cpid1 == 0) {
close(pipefd[0]);
char* str = "Hello my friend!\n";
write(pipefd[1], str, strlen(str));
close(pipefd[1]);
exit(EXIT_SUCCESS);
}
cpid2 = fork();
if (cpid2 == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (cpid2 == 0) {
close(pipefd[1]);
while (read(pipefd[0], &buf, 1) > 0)
write(STDOUT_FILENO, &buf, 1);
close(pipefd[0]);
exit(EXIT_SUCCESS);
} else {
wait(NULL);
}
return EXIT_SUCCESS;
}
ASIDE: WHY SYSTEM CALLS LOOK LIKE PROCEDURE CALLS
You may wonder why a call to a system call, such as open() or read(), looks exactly like a typical procedure call in C; that is, if it looks just like a procedure call, how does the system know it’s a system call, and do all the right stuff? The simple reason: it is a procedure call, but hidden inside that procedure call is the famous trap instruction. More specifically, when you call open() (for example), you are executing a procedure call into the C library. Therein, whether for open() or any of the other system calls provided, the library uses an agreed-upon calling convention with the kernel to put the arguments to open() in well-known locations (e.g., on the stack, or in specific registers), puts the system-call number into a well-known location as well (again, onto the stack or a register), and then executes the aforementioned trap instruction. The code in the library after the trap unpacks return values and returns control to the program that issued the system call. Thus, the parts of the C library that make system calls are hand-coded in assembly, as they need to carefully follow convention in order to process arguments and return values correctly, as well as execute the hardware-specific trap instruction. And now you know why you personally don’t have to write assembly code to trap into an OS; somebody has already written that assembly for you.
or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Do you want to remove this version name and description?
Syncing