4.1 NFS安装与测试
安装NFS网络文件系统的时候,需要用到portmap,portmap将远程调用(RPC)的程序号转化为Internet端口号,NFS我们认为它是一个RPC服务,在启动RPC服务之前要做好端口的对应工作,自然portmap就需要安装。
接下来安装nfs,在服务器端:
安装成功的标志:
服务器端配置:
在末尾添加:/tftpboot 192.168.0.*(rw,sync,no_root_squash),其中*表示“所有”,如果,在末尾添加的是:/tftpboot *( rw,sync,no_root_squash),表示所有网段都可以用,可以增加匹配的成功率。我用的是后一句。
重启portmap,
重启成功的标志:
服务器端重启nfs:
重启成功的标志:
在客户端(同一个terminal下),下载nfs-common
测试nfs。我们将虚拟机自身tftpboot目录下的文件挂载(mount)到mnt目录下。首先我们得知道虚拟机自身的IP地址,用命令Ifconfig,找到inet addr,对应的就是IP地址。如下图,
接下来用命令:sudo mount 192.168.230.128:/tftpboot /mnt,意思是:将IP地址为192.168.230.128的主机根目录下有一个文件夹叫tftpboot里的文件挂载到自己的/mnt目录下。
然后我们转到/mnt目录下用ls -l命令可以看到多出来一些文件,而这些文件正好是/tftpboot下的文件,说明我们的nfs可以用了。
当然在linux下测试可以用了,在uClinux下呢?接下来需要做第一节课第二节课做的事情,首先,需要对内核和用户设置,同样是在/work/uClinux-dist目录下,执行sudo make xconfig,调出Target Platform Selection。选择下图红框里的两项为“Yes”,
接下来File system->Network File System->NFS file system support和Provide NFSv3 client support。如下图。
点击OK,并且保存退出以后,就会进入application configuration如下图,选择Network Applications->portmap。如下图,
再选择BusyBox->mount:support NFS mount->save and exit。如下图,
到/work/uClinux-dist路径下执行sudo make dep
执行完成以后,执行sudo make
Make完成以后的标志:
接下来,将他下载到开发板,第二节课的内容,就不累述了,参看下图。
掉电重启,cd命令转到mnt目录下,可以看到此时的目录下是空的,然后使用mount命令(mount 192.168.0.222:/tftpboot /mnt),然后再到mnt目录下,此时多了几个文件,这几个文件正好是/tftpboot目录下的文件,说明挂载成功。如下图,
4.2 自订开机启动程序
开发板如果上电的时候要它自动运行某些程序,我们可以脚本文件里添加某些命令,具体的路径以及命令如下:
路径:/work/uClinux-dist/vendor/Marvell/Firefox,
命令:sudo gedit rc
在文件的最后一行添加“/bin/hello”,表示在开机以后,系统会先运行bin目录下的hello文件,从而在重启开发板时打印出“Hello,uClinux!”(第二节课的程序,也可以是其他程序),如下图:
然后下载到开发板试一下,在烧录之前要到/work/uClinux-dist目录下执行一下语句:
Sudo make
烧录的命令如下:(具体步骤第2课的2.3小节)
1) tftp 20000 zRomfs
2)fburn 20000 fff70000 length(in hex)
3) tftp 20000 zImage
4)fburn 20000 fff00000 lrngth(in hex)
5)掉电重启
重启以后截图如下:
说明,在开机的时候,系统运行了etc/rc脚本里面的内容。
4.3 登录程序
在开发板上模拟linux的登录:用户输入正确的用户名和密码以后,才能进入shell,如果输错,就会提醒用户再次输入,直到输入正确为止。首先,该程序应该写在哪里面?答案是在/work/uClinux-dist/user/sash的sash.c文件里,打开该文件,有许多的代码,但是,main()函数还是比较好找的,肯定是在mian()函数里加入一个循环,用于登录程序,回忆一下之前每次在下载程序到板子里的时候,重启,最后一句是:“Sash command shell(version 1.1.1)”,然后,我们才进行操作,所以登录程序应该加在用printf()函数打印出这段话的前面,果不其然,在第二个if的else语句里面我们找到这条语句,如下:
else
printf("Sash command shell (version %s)\n", version);
所以,我们的登录程序加在else语句里面,
既然是登录程序,肯定要有真实的用户名(user)和密码(passwd),用输入的用户名和密码与其进行对比,如果一样,就表示登录成功,不一样,肯定登录失败。所以真实的用户名(user)和密码(passwd)保存在哪里?答案是可以自己随便在/work/uClinux-dist/romfs下定义,一般在romfs/etc目录下,所以/work/uClinux-dist/romfs/etc下新建一个文件,
命令:sudo gedit PsWd
设置的用户名为:LiuFarrell
密码:12345678
内容如下:
上图和想设置的数据不一样,这么回事?其实是为了保护数据的安全性加密了的。加密函数crypt();在linux中简单的写一个加密以后的数据测试,如下:
上图中,cry(infor,key)应该改为crypt(infor,key)..................................写错了的。
其中infor变量第一次用“LiuFarrell”,第二次改为“12345678”,就可以分别的到“LiuFarrell”和“12345678”加密以后的数据,如下:
将红框里面的内容分别对应写进PsWd里面就得到了我们想要的数据。
真实的用户名和密码数据已经准备好了,自然就该进入sash.c里面编写代码了。
进入/work/uClinux-dist/user/sash下,打开 sash.c程序,命令:sudo gedit sash.c,在main()函数之前添加如下代码:
#define PATHFILE "passwd"
#if defined(CONFIG_USER_FLATFSD_FLATFSD)
#define PATH_PASSWD "/etc/config/config"
#else
#define PATH_PASSWD "/etc/PsWd" //定义存放真实用户名和密码的路径
#endif
char usernamebuf[128]; //缓冲区
//获取登录user的字符串函数
char *getrealuser(char *pfile)
{
static char tmpline[128];
FILE *fp;
char *sUser;
int len;
if ((fp = fopen(pfile, "r")) == NULL)
{
fprintf(stderr, "ERROR: failed to open(%s), errno=%d \n",
pfile, errno);
return((char *) NULL);
}
while (fgets(tmpline, sizeof(tmpline), fp))
{
sUser = strchr(tmpline, '=');
if (sUser)
{
*sUser++ = 0;
if (strcmp(tmpline, "user") == 0)
{
len = strlen(sUser);
if (sUser[len-1] == '\n')
sUser[len-1] = 0;
return(sUser);
}
}
}
fclose(fp);
return((char *) NULL);
}
获取登录user的密码函数
char *getrealpass(char *pfile)
{
static char tmpline[128];
FILE *fp;
char *spass;
int len;
if ((fp = fopen(pfile, "r")) == NULL)
{
fprintf(stderr, "ERROR: failed to open(%s), errno=%d \n",
pfile, errno);
return((char *) NULL);
}
while (fgets(tmpline, sizeof(tmpline), fp))
{
spass = strchr(tmpline, '=');
if (spass)
{
*spass++ = 0;
if (strcmp(tmpline, "passwd") == 0)
{
len = strlen(spass);
if (spass[len-1] == '\n')
spass[len-1] = 0;
return(spass);
}
}
}
fclose(fp);
return((char *) NULL);
}
在main()函数的第二个if条件语句的else里添加加粗部分的代码,也就是说在登录进入shell以前,要先进行用户名和密码的判定。
else
{
printf("###############-Please Login!-###################\n");
for(;;)
{
char *cryptmode;
char *realuser,*inputuser;
char *realpasswd,*inputpasswd;
char *p;
cryptmode = "ab";
printf("User: ");
fflush(stdout);
fgets(usernamebuf, sizeof(usernamebuf), stdin);
p = strchr(usernamebuf, '\n');
if( p != 0 )
*p=0;
realuser = getrealuser(PATH_PASSWD);
if(usernamebuf)
{
if(strcmp(crypt(usernamebuf,cryptmode),realuser) == 0)
{
inputpasswd = getpass("Passwd: ");
realpasswd = getrealpass(PATH_PASSWD);
if(strcmp(crypt(inputpasswd,cryptmode),realpasswd) == 0)
{
printf("Login successfully!\n");
break;
}
}
else printf("The user name is invaild!\n");
}
else printf("Wrong input!\n");
}
printf("Sash command shell (version %s)\n", version);
}
下载到开发板运行如下,
只有在正确输入用户名和密码以后才能进入shell,说明实验成功。
4.4 总结
本次课对我来说是有一定难度的,主要难在不知道程序或者命令应该写在哪里,网上也有许多教程,但都不是关于uClinux的,所以就不想看,通过和同学交流,才慢慢的完成了本次的练习,受益匪浅。