Experimental operating system a system call to value added value and close the thread to read and write
Operating System: ubuntu
Kernel version: kernel5.5.5
The whole idea of a
The computer user mode and kernel mode is divided into two states, the upper space is the user mode application is restricted from direct contact with the bottom. Direct control of the hardware kernel mode, provides the operating environment for the user mode. There are visits between the two control tube, does not allow direct access. If you enter the kernel mode from user mode, you need a system call. System call interface function is a series of user mode and kernel mode.
Add their own system calls, you need three steps.
First, the system call table to add system calls
Second, the declaration system call service routine prototype
Third, to achieve system calls
After modifying the kernel code completion, compiling restart, you can call your own system calls the function.
Call functions functions implemented: incoming pid, and can read value prio value of the process, you can modify the value value, you can kill the process.
Two specific implementation
My kernel version is 5.5.5, so the kernel root directory in usr / src / linux-5.5.5, enter the directory operations
First, the system call table to add system calls
System call table is ./arch/x86/entry/syscalls/syscall64.tbl
Add the system call number in the tail of the table
Name service routine entry unoccupied call number x32 / x64 / common system calls
550 common mysetprocess __x64_sys_mysetprocess
II.
Service routine prototype declaration ./include/linux/syscalls.h
asmlinkage int sys_mysetprocess(pid_t pid, int flag, int nicevalue,void __user * prio, void __user * nice);
Five parameters:
pid: pid operation thread
flag: operation code, read the value 0, the value of a modified value, the process kills 2
nicevalue: To modify the value value
prio, nice: copy_to_user call () function to read the kernel mode prio, nice delivered to the user
Third, to achieve system calls
在./kernel/sys.c中实现系统调用函数
```
SYSCALL_DEFINE5(mysetprocess,pid_t,pid, int, flag, int, nicevalue,void __user *, prio, void __user *, nice){
if(find_get_pid(pid)==NULL){
printk("input pid error.");
return EFAULT;
}
struct pid * kpid;
struct task_struct * task;
kpid = find_get_pid(pid);
task = pid_task(kpid,PIDTYPE_PID);
int cur_nice;
int cur_prio;
cur_nice=task_nice(task);
cur_prio=task_prio(task);
if(flag==1){
//set process's nice
set_user_nice(task,nicevalue);
cur_nice=task_nice(task);
cur_prio=task_prio(task);
printk("the nice value is changed!\n");
printk("current nice is %d and piro is %d.\n",cur_nice,cur_prio);
}else if(flag==0){
//get process's nice
printk("current nice is %d and piro is %d.\n",cur_nice,cur_prio);
}else if(flag==2){
//safely kill process by pid
kill_pid(kpid,SIGTERM,1);
printk("process is killed safely.\n");
return 0;
}else{
printk("operate failed.\n");
return EFAULT;
}
copy_to_user(prio,&cur_prio,sizeof(cur_prio));
copy_to_user(nice,&cur_nice,sizeof(cur_nice));
return 0;
}
Function uses the simple instructions
find_get_pid(pid_t nr)
The obtained process ID nr process descriptor struct pid
pid_task(struct pid* pid,enum pid_type)
PIDTYPE_PID indicates process numbers and in accordance with the process
According to the process descriptor returned task descriptor
task_nice(const struct task_struct *p ),nice范围-20-19
Return process nice value
task_prio(const struct task_struct *p)
Return process prio value
set_user_nice(struct task_struct *p, long nice)
nice value of the process
kill_pid(struct pid *pid, int sig, int priv)
sig program is set to end SIGTERM signal, SIGTERM can be blocked and processing, to program exits normally.
priv set to 1, SEND_SIG_PRIV transmission signal,
Send process descriptor, the end of the signal, kill the process
copy_to_user(void __user *to, const void *from, unsigned long n)
Copying the contents from the kernel space to user space
n represents Copy space
Fourth, compile the kernel
Compile the kernel time-consuming (single-core, then to two hours), occupies a large space (space ready at least 30G), be patient
Under linux-5.5.5 directory
After the make menuconfig select save exit
make -j4 (recommended multicore compilation, about twice as fast, the virtual machine is allocated more parameters can audit more)
make modules_install
make install
Use to view the current kernel version uname -r to determine whether successful compilation
make clean clean up the build files (must use, prior to cleaning compiled footprint)
Restart
If the compiler has problems, it is recommended to see this article https://www.govzzp.cn/?p=198, described in great detail
Fifth, the test system call
Write c program, test the system call whether to add a success
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
int main(){
int pid,flag,nicevalue,prio,nice;
char control;
printf("请输入pid:\n");
scanf("%d",&pid);
printf("读入:0,修改:1, 杀死: 2 \n");
scanf("%d",&flag);
if(flag!=0&&flag!=1&&flag!=2){
printf("输入错误");
return 1;
}
if(flag==0){
int res = syscall(550,pid ,flag,0,&prio,&nice);
if(res!=0){
printf("进程不存在!\n");
return 1;
}
printf("进程的nice值为%d,prio值为%d\n",nice,prio);
}else if(flag==1){
printf("请输入要修改的nice值:\n");
scanf("%d",&nicevalue);
int res = syscall(550,pid,flag,nicevalue,&prio,&nice);
if(res!=0){
printf("进程不存在!\n");
return 1;
}
printf("修改成功!\n");
printf("进程的nice值为%d,prio值为%d\n",nice,prio);
}else if(flag==2){
int res = syscall(550,pid,flag,0,&prio,&nice);
if(res!=0){
printf("进程不存在!\n");
return 1;
}
printf("杀死进程成功.\n");
}
return 0;
}
Test run:
dmesg logging in
success!