nios软核cpu中架构类shell的一种解决方式『linux 系统函数调用的方法』

43 篇文章 0 订阅
16 篇文章 1 订阅

在nios中要实现一个类shell的交互系统,用户在终端可以通过命令调用系统函数。
想到linus当年在写下系统函数调用时,其实基于的思想是一样的,就是查表,每一种系统函数都对应一种中断服务号,然后通过0x80系统调用进入内核,然后查表,这里就可以找到对应的内核系统函数,回顾一下linus是怎么做到的。
就以系统函数open为例子

int open(const char * filename, int flag, ...)
{
 register int res;
 va_list arg;
 va_start(arg,flag);
 __asm__("int $0x80"
  :"=a" (res)
  :"0" (__NR_open),"b" (filename),"c" (flag),
  "d" (va_arg(arg,int)));
 if (res>=0)
  return res;
 errno = -res;
 return -1;
}

这个open函数是一个变参函数,对变参函数的研究在前面用一片博文已经讲过,不多说。
主要看着这几个重要代码

"int $0x80"
:"0" (__NR_open)

这是软件调用,__NR_open是传入的参数,是一个宏定义

#define __NR_open   5

对与0x80这个中断号,需要在找到中断向量表其对应的中断向量,
在调度初始化函数sched.c中有

set_system_gate(0x80,&system_call);

就是对应中断0x80的中断向量为system_call,所以这就是为什么大家叫0x80是系统函数调用中断号了。

看看systen_call

_system_call:
 push %ds
 push %es
 push %fs
 pushl %eax  # save the orig_eax
 pushl %edx  
 pushl %ecx  # push %ebx,%ecx,%edx as parameters
 pushl %ebx  # to the system call
 movl $0x10,%edx    # set up ds,es to kernel space
 mov %dx,%ds
 mov %dx,%es
 movl $0x17,%edx    # fs points to local data space
 mov %dx,%fs
 cmpl _NR_syscalls,%eax
 jae bad_sys_call
 call _sys_call_table(,%eax,4)
 pushl %eax

看重要的几句代码

cmpl _NR_syscalls,%eax 
call _sys_call_table(,%eax,4) 

第一句对比传进来的参数,以确定需要调用什么系统函数
第二句调用相应的系统函数

fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending, sys_sethostname,
sys_setrlimit, sys_getrlimit, sys_getrusage, sys_gettimeofday, 
sys_settimeofday, sys_getgroups, sys_setgroups, sys_select, sys_symlink,
sys_lstat, sys_readlink, sys_uselib };

这其实是一个数组,其中typedef int (*fn_ptr)();
所以是函数指针数组,中断服务号作为数组的下标查表,
上面知道open的服务号是5,则 sys_call_table[5]确实对应着函数 sys_open的地址。
所以这样就完成的整个一个从用户到内核的调用,如图所示
这里写图片描述


所以在 nois中开发一个类shell的交互系统,是可以借鉴这个模型的,在对这个模型简化一下,这里面最重要的是那个表(函数指针数组),在nios是是单线程跑的,所以中断这块可以去掉,利用查询的方式来完成。还有就是如何将用户输入的命令和系统命令匹配起来,是否还是想linus一样采用数字来对应,但是实际用户输入的是字符串,所以是否字节是字符串匹配,既然是字符串就不可以是用数组下标的方式了,想到c++中的map类;这是一种关联变量,为此可以写一个结构体,也可以达到这种效果。

typedef struct key
{
    用户命令字符串;
    用户参数;
    命令处理函数;
}KEY;

实际这就是一个命令所有相关的东西,然后用数组将这些命令结构体存储起来。

KEY  cmd_table[];

通过对比每个结构体的第一个成员,以确定命令然后调用命令函数。
这里写图片描述
最终实现的初始化cmd_table如下
这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值