实现方式
基础版本的进程间通信比较简单,由三个系统调用完成
linux/arch/x86/entry/syscalls/syscall_64.tbl
新增三个系统调用[作者使用的源码是最新版]
1 2 3 4 # follow three syscall is used for process_communication442 common zqd_call sys_zqd_call443 common zqd_server sys_zqd_server444 common zqd_reply sys_zqd_reply
linux/arch/x86/kernel/sys_x86_64.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 char data[50 ];unsigned long rpc_data_len;long rpc_result; DECLARE_COMPLETION(RPC_reply_done); DECLARE_COMPLETION(RPC_call_done); SYSCALL_DEFINE2(zqd_call,void *,rpc_data,size_t ,data_len) { printk(KERN_INFO "zqd_call...\n" ); if (copy_from_user(data,rpc_data,data_len)) { printk(KERN_INFO "zqd_call: failed to copy data to buffer! \n" ); return 0 ; } rpc_data_len = data_len; complete(&RPC_call_done); wait_for_completion(&RPC_reply_done); printk(KERN_INFO "rpc_result = " , rpc_result); return rpc_result; } SYSCALL_DEFINE2(zqd_server,void *,buf,size_t *,data_len) { printk(KERN_INFO "zqd_server...\n" ); wait_for_completion(&RPC_call_done); if (copy_to_user(buf,data,rpc_data_len)) { printk(KERN_INFO "zqd_server: failed to copy data to buffer! \n" ); return 0 ; } put_user(rpc_data_len,data_len); return 0 ; } SYSCALL_DEFINE1(zqd_reply,long ,result) { printk(KERN_INFO "zqd_reply...\n" ); rpc_result = result; complete(&RPC_reply_done); return 0 ; }
测试用例:
client.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <unistd.h> #include <stdio.h> #include <string.h> #define __NR_zqd_call 442 typedef unsigned long size_t ;int main (int argc, char const *argv[]) { char *data = "Hi, top!" ; size_t data_len = strlen (data) + 1 ; long zqd_call_result = syscall(__NR_zqd_call,data,data_len); printf ("zqd_call_result = %ld\n" , zqd_call_result); printf ("\n" ); return 0 ; }
server.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <unistd.h> #include <stdio.h> #define __NR_zqd_server 443 #define __NR_zqd_reply 444 int main (int argc, char const *argv[]) { char buffer [20 ]; long data_len; long result_server = syscall(__NR_zqd_server,buffer ,&data_len); long result_reply = syscall(__NR_zqd_reply,2048 ); printf ("data_len = %ld\n" , data_len); printf ("data = %s\n" , buffer ); printf ("server end...\n" ); printf ("result_server: %ld\n" ,result_server); printf ("result_reply: %ld\n" ,result_reply); return 0 ; }
实践小结
服务端正确的打开方式:
启动qemu之后,找到编译后的server.out和client.out
先执行
再执行
以上代码完成了简化版本的进程间通信,注意编译的时候加上-static参数。如有错误请联系作者更正