建立对系统调用接口的深入认识
掌握系统调用的基本过程
能完成系统调用的全面控制
为后续实验做准备
在kernal/who.c中实现iam()的系统调用。
在kernal/who.c中实现whoami()的系统调用。
测试程序,得到一下结果:
\$ ./iam lizhijun
\$ ./whoami
lizhijun
cd ~/oslab
tar zxvf hit-oslab-linux-20110823.tar.gz
从中可以看到已经排到了71号,那么继续排:
#define __NR__iam 72
#define __NR__whoami 73
首先要进入linux-0.11目录make all,然后sudo
cd linux-0.11/
make all
cd ..
sudo ./mount-hdc
sudo umount hdc
nr_system_calls = 74
这里需要添加sys_iam和sys_whoami的引用,如图:
首先再kernel建立who.c
模仿sys_close写sys_iam和sys_whoiam:
#define __LIBRARY__
#include
#include
char sys_name[25];
int sys_iam(const char * name){
int count=0;
while(*(name+count)!='\0'){
count++;
}
if(count>23){
errno=ENIVAL;
return -1;
}
else{
for(int i=0;i<=count;i++){
sys_name[i]=*(name+i);
}
return count;
}
}
int sys_whoami(char* name, unsigned int size){
int i=0;
while(sys_name[i]!='\0'){
i++
}
if(size-1;
return -1;
}
else{
for(i=0;i<=size;i++){
*(name+i)=sys_name[i];
}
return size;
}
}
OBJS = sched.o system_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
signal.o mktime.o
改为:
OBJS = sched.o system_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
signal.o mktime.o who.o
\### Dependencies:
exit.s exit.o: exit.c ../include/errno.h ../include/signal.h \
../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
../include/asm/segment.h
改为:
\### Dependencies:
who.s who.o: who.c ../include/linux/kernel.h ../include/unistd.h
exit.s exit.o: exit.c ../include/errno.h ../include/signal.h \
../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
../include/asm/segment.h
make all
发生了错误。修改who.c的内容,并加入printk():
#define __LIBRARY__
#include
#include
char sys_name[25];
int sys_iam(const char * name){
int i=0;
int count=0;
while(*(name+count)!='\0'){
count++;
}
if(count>23){
errno=EINVAL;
return -1;
}
else{
for(i=0;i<=count;i++){
sys_name[i]=*(name+i);
}
return count;
}
}
int sys_whoami(char* name, unsigned int size){
int i=0;
while(sys_name[i]!='\0'){
i++
}
if(sizereturn -1;
}
else{
for(i=0;i<=size;i++){
*(name+i)=sys_name[i];
}
return size;
}
在hdc/user/root下编写iam.c,whoami.c:
iam.c:
#define __LIBRARY__
#include
#include
_syscall1(int,iam,const char*,name)
int main(int argc, char* argv[]){
if(argc<0){
printf("No Name!");
}
else{
printf("Please input your name:");
iam(argv[1]);
}
return 0;
}
whoiam.c:
#define __LIBRARY__
#include
#include
_syscall2(int,whoami,char*,name,unsigned int,size)
int main(int argc,char* argv[]){
char name[24]={0};
whoami(name,24);
printf("my name is %s",name);
return 0;
}
测试效果如下:
这里输出了我的信息,但不能输入。(用printk的时候会发生iam.o文件不能编译的问题,暂时不能解决,用了printf作代替)
从文档可以看出需要使用get_fs_byte和put_fs_byte来与用户空间交互,于是修改who.c中的代码:
#define _LIBRARY_
#include
#include
char sys_name[25];
int sys_iam(const char * name){
int i=0;
int count=0;
while(get_fs_byte(name+count)!='\0'){
count++;
}
if(count>23){
errno=EINVAL;
printk("string is too long");
return -1;
}
else{
for(i=0;i<=count;i++){
sys_name[i]=*(name+i);
}
printk("copy finished");
return count;
}
}
int sys_whoami(char* name, unsigned int size){
int i=0;
while(sys_name[i]!='\0'){
i++;
}
if(size"size is not enough");
return -1;
}
else{
for(i=0;i<=size;i++){
put_fs_byte(sys_name[i],(name+i));
}
printk("copy finished");
return size;
}
}
test2.c:
发现不一致都是大于23个字符时的,因为格式的问题。通过。
这次实验遇到了太多麻烦,尤其这个编译很麻烦,每次hdc还要mount很多次才能完成,最终还是参考了别人的实验报告,并进行理解才能完成。非常心累。
从Linux 0.11现在的机制看,它的系统调用最多能传递几个参数?你能想出办法来扩大这个限制吗?
3个吧,因为最多就是syscall3。如果要更多的话就定义syscall4,styscall5之类的,以满足更多参数调用的需求。
用文字简要描述向Linux 0.11添加一个系统调用foo()的步骤。
调整unistd.h中的内容,比如加NR什么的,并改系统调用的总数等内容->添加系统调用的引用->实现最后的sys_xxx->修改makefile的过程,最后进行编译即可。
最后的who.c文件:
#define __LIBRARY__
#include
#include
#include
char sys_name[25]={0};
int sys_iam(const char * name){
int i=0;
int count=0;
while(get_fs_byte(name+count)!='\0'&&count<25){
count++;
}
if(count>23){
errno=EINVAL;
printk("string is too long");
return -1;
}
else{
for(i=0;i<=count;i++){
sys_name[i]=get_fs_byte(name+i);
}
printk("copy finished");
return count;
}
}
int sys_whoami(char* name, unsigned int size){
int i=0;
int rs=0;
while(sys_name[i]!='\0'&&i<25){
i++;
}
if(size"size is not enough");
return -1;
}
else{
for(rs=0;rs<=i;rs++){
put_fs_byte(sys_name[rs],(name+rs));
}
printk("copy finished");
return i;
}
}
最后的iam.c:
#define __LIBRARY__
#include
#include
#include
int main(int argc, char* argv[]){
if(argc>1){
if(iam(argv[1])<0){
return -1;
}
else
return -1;
}
return 0;
}
最后的whoami.c:
#define __LIBRARY__
#include
#include
#include
int main(int argc,char* argv[]){
char name[100]={0};
if(whoami(name,24)<0)
return -1;
else
printf("%s\n",name);
return 0;
}
最后的name.h:
#define __LIBRARY__
#include
#include
#include
_syscall1(int,iam, const char*, name)
_syscall2(int,whoami,char*,name,unsigned int,size)
就这样了,好累啊