---
# System prepended metadata

title: Linux Project 1

---

# Linux Project 1
## Environment

- Kernel vesion : 5.15.137
- 作業系統 : ubuntu 22.04

## Kernel 編譯過程
下載欲編譯的kernel source code, 新增system call後執行以下指令：
```bash=
sudo apt install build-essential libncurses-dev libssl-dev libelf-dev bison flex -y
sudo make oldconfig

sudo make -j4
sudo make modules_install -j4
sudo make install -j4
```

## 編譯時遇到的問題d
- 我們有遇到無法編譯成功的情況，發生的問題每次、每個組員都遇到不同問題，但是經過幾次更換版本之後問題就大部分解決了
- 執行sudo make時遇到其中一個問題："FAILED: load BTF from vmlinux: No such file or directory", 只要下載套件dwarves即可解決
```
sudo apt install dwarves 
```
## 新增System Call過程
#### 在linux-5.15.137 directory中創建資料夾vtop, 並在創建的資料夾中新增system call：
```
cd /usr/src/linux-5.15.137
mkdir vtop
cd vtop
vim vtop.c
```
#### 同時創建Makefile並寫入:
```
obj-y := vtop.o
```
#### 接著回上個目錄改 Makefile, 將剛剛新增的資料夾加到路徑中：
```
cd ..
vim Makefile
```
![image](https://hackmd.io/_uploads/rk03pyfSa.png)
#### 修改syscall_64.tbl:
```
vim arch/x86/entry/syscalls/syscall_64.tbl
```
![image](https://hackmd.io/_uploads/ryCm0kMHT.png)

#### 修改syscalls.h(添加syscall原型)
```
vim include/linux/syscalls.h
```
![image](https://hackmd.io/_uploads/r1x81eMr6.png)

## System Call
- Linux 在 2.6.10 中引入了四層的頁表輔助虛擬地址的轉換(PGD、PUD、PMD、PTE)，在 4.11 中引入了五層的頁表結構(多了一層P4D，也就是：PGD、P4D、PUD、PMD、PTE)。
- 與pud_none(pud_t), pmd_none(pmd_t)不同的是，p4d_none(p4d_t)=True並不一定代表程式出錯，linux kernel會自動幫我們映射到下一層，即回傳(p4d_t)*pgd。
- 依照題目要求，大多system call失敗時會回傳-1，這邊我們改成：失敗return 0，成功則return傳入function之virtual address所對應的physical address。
```C=
#include <linux/mm.h>        // struct mm_struct
#include <linux/sched.h>     // current 宏
#include <linux/syscalls.h>  // SYSCALL_DEFINE 宏
#include <linux/uaccess.h>   // __user 宏
#include <asm/pgtable.h>     // 頁表相關的結構和宏 (pgd_t, pmd_t, pte_t)
```

## Multithread.c
```C=
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>



sem_t sem;

__thread int TLS = 0;
int data = 0;
int bss ;

void code(){
	return ;
}

void* thread_function(void* thread_num){
	sem_wait(&sem);
	printf("----------------Thread %d -------------------\n", (int) thread_num);
	int stack = 7;
	char* sname[] = {"TLS","data","bss","code","stack","heap","lib"};
	int *heap = malloc(sizeof(int));

	unsigned long linear_address[] = {
		(unsigned long) &TLS,
		(unsigned long) &data,
		(unsigned long) &bss,
		(unsigned long) &code,
		(unsigned long) &stack,
		(unsigned long) heap,
		(unsigned long) &printf
	};
	
	for(int i=0;i<stack;i++){
		unsigned long vaddr = linear_address[i];
		unsigned long paddr = syscall(449,vaddr);
		printf("%s: Linear address: %#lx , Physical address: %#lx \n", sname[i],vaddr,paddr);
	}
	sem_post(&sem);
	return NULL;
}

void main(){
	pthread_t thread1 , thread2, thread3;
	sem_init(&sem,0,1);
	
	pthread_create(&thread1, NULL, thread_function, (void*)1);
	pthread_create(&thread2, NULL, thread_function, (void*)2);
	pthread_create(&thread3, NULL, thread_function, (void*)3);

	pthread_join(thread1, NULL);
	pthread_join(thread2, NULL);
	pthread_join(thread3, NULL);

	sem_destroy(&sem);

	return;
}

```
### 編譯
```
gcc -o mt multithread.c -pthread
```
## multithread.c 執行結果
![image](https://hackmd.io/_uploads/rkJ-UuhE6.png)


## 各Thread在Physical Memory的Layout

### Thread1
![image](https://hackmd.io/_uploads/ByMgZK3ET.png)

### Thread2
![image](https://hackmd.io/_uploads/HyGW-K246.png)

### Thread3
![image](https://hackmd.io/_uploads/r1jb-K346.png)


## Example Code
- 增加了heap區段
- 加入semaphore，避免thread交互執行導致難以觀察結果
```C=
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <sys/syscall.h>      /* Definition of SYS_* constants */
#include <unistd.h>
#include <semaphore.h>

extern void *func1(void *);
extern void *func2(void *);
extern int main();
void * my_get_physical_addresses(void *);
		 
void * my_get_physical_addresses(void *v_addr){
    unsigned long vaddr = (unsigned long)v_addr;

    unsigned long p_addr = syscall(449, vaddr);
    unsigned long *p_ptr = (unsigned long *)p_addr;
    return p_ptr;
}

struct data_
{
    int  id ;
    char name[16] ;
};
typedef struct data_ sdata ;
static __thread  sdata  tx ;  //thread local variable
sem_t sem;
int a=123;  //global variable

void hello(int pid)
{
    int b=10;   //local varialbe
    int *heap = malloc(sizeof(int));  //heap area
    b=b+pid;
    //global variable
    printf("In thread %d \nthe value of gloable varialbe a is %d, the offset of the logical address of  a is %p, ", pid, a, &a);
    printf("the physical address of global variable a is %p\n", my_get_physical_addresses(&a) );
    //local variable
    printf("the value of local varialbe b is %d, the offset of the logical address of b is %p, ", b, &b);
    printf("the physical address of local variable b is %p\n", my_get_physical_addresses(&b));
    //heap
    printf("the value of the logical address of heap area is %p, ", heap);
    printf("the physical address of heap area is %p\n", my_get_physical_addresses(heap));
    //thread local variable
    printf("the offset of the logical address of thread local varialbe tx is %p, ", &tx);
    printf("the physical address of thread local variable tx is %p\n", my_get_physical_addresses(&tx));
    //function
    printf("the offset of the logical address of function hello is %p, ", hello);
    printf("the physical address of function hello is %p\n", my_get_physical_addresses(hello));
    printf("the offset of the logical address of function func1 is %p, ", func1);
    printf("the physical address of function func1 is %p\n", my_get_physical_addresses(func1));
    printf("the offset of the logical address of function func2 is %p, ", func2);
    printf("the physical address of function func2 is %p\n", my_get_physical_addresses(func2));
    printf("the offset of the logical address of function main is %p, ", main);
    printf("the physical address of function main is %p\n", my_get_physical_addresses(main));
    //library function
    printf("the offset of the logical address of library function printf is %p, ", printf);
    printf("the physical address of library function printf is %p\n", my_get_physical_addresses(printf));
    printf("====================================================================================================================\n");

}  

void *func1(void *arg)
{
    char *p = (char*) arg ;
    int pid  ;
    pid =  syscall( __NR_gettid );
    tx.id = pid ;
    strcpy(tx.name,p) ;
    sem_wait(&sem);
    printf("I am thread with ID %d executing func1().\n",pid);
    hello(pid);
    sem_post(&sem);
    while(1)
    {
        //printf("(%d)(%s)\n",tx.id,tx.name) ;
        sleep(1) ;
    }
}

void *func2(void *arg)
{
    char *p = (char*) arg ;
    int pid  ;
    pid =  syscall( __NR_gettid );
    tx.id = pid ;
    strcpy(tx.name,p) ;
    sem_wait(&sem);
    printf("I am thread with ID %d executing func2().\n",pid);
    hello(pid);
    sem_post(&sem);
    while(1)
    {
        //printf("(%d)(%s)\n",tx.id,tx.name) ;
        sleep(2) ;
    }
}
int main()
{ 
    pthread_t id[2];
    sem_init(&sem, 0, 1);
    char p[2][16] ;
    strcpy(p[0],"Thread1") ;      
    pthread_create(&id[0],NULL,func1,(void *)p[0]);
                   
    strcpy(p[1],"Thread2") ;
    pthread_create(&id[1],NULL,func2,(void *)p[1] );
                   
    int pid  ;
    pid =  syscall( __NR_gettid );
    tx.id = pid ;
    strcpy(tx.name,"MAIN") ;
    sem_wait(&sem);
    printf("I am main thread with ID %d.\n", pid);
    hello(pid);
    sem_post(&sem);

    sem_destroy(&sem);
    while(1)
    {
        //printf("(%d)(%s)\n",tx.id,tx.name) ;
        sleep(5) ;
    }
}

```

### Example Code 執行結果
![image](https://hackmd.io/_uploads/HkFZBKhVp.png)



## Reference
1.[add a system call教學網址 by 助教](https://hackmd.io/aist49C9R46-vaBIlP3LDA?both)
2.[新增system call](https://hackmd.io/@combo-tw/Linux-%E8%AE%80%E6%9B%B8%E6%9C%83/%2F%40combo-tw%2FBJPoAcqQS#%E5%A6%82%E4%BD%95%E6%96%B0%E5%A2%9E%E4%B8%80%E5%80%8B-System-Call)
3.[Linux轉址以及Virtural Memory](https://iter01.com/510311.html)
4.[Linux Page Tables](https://docs.kernel.org/mm/page_tables.html)
5.[copy_to_user&copy_from_user](https://blog.51cto.com/u_16087831/6223592)