owned this note
owned this note
Published
Linked with GitHub
> []# 2017 OS note
## Address Spaces of p_proc & c_proc
### fork()
```cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int x=0;
int main()
{
pid_t pid;
/* fork another process */
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed");
exit(-1);
}
else if (pid == 0) { /* child process */
x++;
exit(0);
}
else { /* parent process */
/* parent will wait for the child to complete */
wait (NULL);
printf ("%d",x);
exit(0);
}
} //parent and child use distinct mem space, x is 0
```
### vfork()
```cpp=
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int x=0;
int main()
{
pid_t pid;
/* fork another process */
pid = vfork();
if (pid < 0) { /* error */
fprintf(stderr, "Fork Failed");
exit(-1);
}
else if (pid == 0) { /* child proc */
x++;
_exit(0);
}
else { /* parent proc */
/* parent will wait for the child */
wait (NULL);
printf ("%d",x);
exit(0);
}
} //child use parent's mem space, x is 1
```
# hw3
## <thread.h>
> Thread is either **joinable** or **detached**.
> compile and link with pthread library
> gcc **-l pthread** code.c
> gcc **-pthread** code.c
```cpp
include <pthread.h>
typedef unsigned long pthread_t;
```
### pthread_create()
[@](http://man7.org/linux/man-pages/man3/pthread_create.3.html)
> create new thread
```c
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
```
* execution by invoking `start_routine(arg)`
* 若成功 create thread,其 thread id 會存在 `*thread`。
* thread 會在以下幾種情況下結束:
* 自己呼叫 `pthread_exit()`
* `start_routine(arg)` 呼叫 `return`
* 被 `pthread_cancel()` 中止
* 同 process 內有 thread 呼叫 `exit()`,該 process 所有 thread 都會結束。
* create joinable thread by default
* create detached thread
```c
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, THREAD_FUNCTION, arg);
```
#### pthread_detach() [@](http://man7.org/linux/man-pages/man3/pthread_detach.3.html)
* create joinable thread and detach it
```c
pthread_t tid;
pthread_create(&tid, NULL, THREAD_FUNCTION, arg);
pthread_detach(tid);
```
* 當一個 thread 成為 detached,就無法再變為 joinable,也無法呼叫 `pthread_join()` 。
### pthread_join()
[@](http://man7.org/linux/man-pages/man3/pthread_join.3.html)
> join with a terminated(zombie) thread
> 類似 wait terminated process
```c
int pthread_join(pthread_t tid, void **retval);
```
* wait 該 `tid` 指定的 thread
* 如果 `retval` 非 NULL,會接到該 thread 的 exit status
* 同 process 底下的任一 thread 可以 join 其他 thread
* `<pthread.h>` 沒有任何函式的行為類似 `waitpid(-1, &status, 0)`
* 也就是 "join with any terminated thread" 是不合理的設計。
### pthread_exit()
[@](http://man7.org/linux/man-pages/man3/pthread_exit.3.html)
> terminate calling thread
> 用 return 也可
```c
void pthread_exit(void *retval);
```
`*retval` 指向此 thread 的 exit status,此值不能放在這個 thread 的 stack 內,因為 `pthread_exit()` 呼叫之後,此 thread 的 stack 就無法取用了。
* 若 thread 是 joinable
* 用`pthread_exit()` 結束的 thread 並不會 return 回 caller。
* 同 process 內的其他 thread 可以用 `pthread_join()` 來回收已結束的 zombie thread,並可用 `retval` 取得 `pthread_exit()`的 exit status,要注意型別是 `*void`
* `pthread_exit()` 只會關掉 thread,要呼叫 `pthread_join()` 才會釋放 thread 用的資源。
* 若 thread 是 detached
* `pthread_exit()` 會直接釋放資源。
[Ref.](http://blog.csdn.net/scanery/article/details/7241890)
[pthread_exit vs. return](https://stackoverflow.com/questions/3692591/return-versus-pthread-exit-in-pthread-start-functions)
### pthread_self()
[@](http://man7.org/linux/man-pages/man3/pthread_self.3.html)
> obtain id of the calling thread
```c
pthread_t pthread_self(void)
```
在同 process 生出的 thread,其 id 會是唯一的。
`pthread_t` type should be considered **opaque**.
>POSIX 同意 thread_id 可以以不同方式實作
`pthread_self()` 回傳 `pthread_t`<abbr title="unsigned long"> </abbr>
也可使用 `struct` 實作
因此,若要比較 thread_id,應使用 `pthread_equal()` 而不能用 `==`
>在 linux 中,系統將每個 thread 視為個別的 process。
`gettid()` 是 linux 的 system call,not portable,回傳型別為`pid_t`。
`gettid()` 回傳的數值是 kernel 賦予每個 thread 的 process id,跟 POSIX 實作的 thread id 是不同的。
[Ref.](http://blog.csdn.net/hp_truth/article/details/42424769)
### opaque data type
常用來實作 abstract data type,即資料結構未定義的 data type。
> eg. `struct` in C
對於 user 來說,這個 type 的實作是 invisible,
要操作、修改這種 type,必須要使用能 access 其隱藏資訊的 subroutine。
### example
[@](http://blog.xuite.net/nikoung/wretch/154071878-Pthread+%E7%A8%8B%E5%BC%8F%E6%92%B0%E5%AF%AB)
```c=
#include <stdio.h>
#include <pthread.h>
#include <unistd.h> //for sleep()
void *show_message( void *ptr ){
char *message;
message = (char *) ptr;
int x = 5;
for(x = 5 ; x > 0 ; --x){
printf("%s \n", message);
sleep(1);
}
pthread_exit((void *)1234);
}
int main(){
pthread_t thread1;
char *msg1 = "Thread 1";
void *ret;
pthread_create(&thread1, NULL , show_message , (void*) msg1);
pthread_join( thread1, &ret);
printf("return value from thread1 = %d\n",ret);
system("pause");
return 0;
}
```
## <semaphore.h>
> semaphore is a long named as `sem_t`
> compile and link with pthread library
> gcc **-l pthread** code.c
> gcc **-pthread** code.c
[參考網站](http://www.syscom.com.tw/ePaper_Content_EPArticledetail.aspx?id=213&EPID=176&j=5&HeaderName=NonStop%E5%B0%88%E6%AC%84)
### [sem_init()](http://man7.org/linux/man-pages/man3/sem_init.3.html)
> initialize an unnamed semaphore
```c
int sem_init(sem_t *sem, int pshared, unsigned int value);
```
* 初始化一個 semaphore 到 `sem` 指到的位址。
* 當 `pshared` 為 0,此 semaphore 只能被該 process 使用。
* semaphore 要放在 global 或 heap 才能被所有 thread 共享。
* 當 `pshared` 非 0,此 semaphore 能被所有 process 共享。
* semaphore 要放在 shared memory 才能被所有 process 共享。
* 若系統不支援 process-shared semaphore 會回傳`ENOSYS`
* `value` 為此信號機初始值。
* 對 named semaphore 重複初始化會造成無法預期的錯誤。
### [sem_destroy()](http://man7.org/linux/man-pages/man3/sem_destroy.3.html)
> destroy an unnamed semaphore
```c
int sem_destroy(sem_t *sem);
```
* 把 `sem` 指到的信號機 destroy
* 只有被 `sem_init()` 初始化的信號機需要被 `sem_destroy()` 。
### [sem_post()](http://man7.org/linux/man-pages/man3/sem_post.3.html)
> unlock a semaphore
> sem + 1
```c
int sem_post(sem_t *sem);
```
sem 的 value + 1
信號機的 value > 0,即 unlock,可進入。
`sem_post()` 後 value > 0,會去把被 `sem_wait()` block 住的叫醒。
### [sem_wait()](http://man7.org/linux/man-pages/man3/sem_wait.3.html)
> lock a semaphore
> sem - 1
```c
int sem_wait(sem_t *sem);
//throw error if blocked
int sem_trywait(sem_t *sem);
//throw error if timeout
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
```
sem 的 value - 1
信號機的 value = 0,即 lock,無法進入。
* 若呼叫 `sem_wait()` 後 value > 0,立即 return。
* 若呼叫 `sem_wait()` 後 value = 0,block this function call。
### [sem_getvalue()](http://man7.org/linux/man-pages/man3/sem_getvalue.3.html)
> get the value of a semaphore
```c
int sem_getvalue(sem_t *sem, int *sval);
```
把`sem`的值存到 `sval` 指到的地方,呼叫成功回傳 0
## hw7
黑魔法:[posix_fallocate](http://man7.org/linux/man-pages/man3/posix_fallocate.3.html)