嵌入式linux实验报告.docx
《嵌入式linux实验报告.docx》由会员分享,可在线阅读,更多相关《嵌入式linux实验报告.docx(28页珍藏版)》请在冰豆网上搜索。
嵌入式linux实验报告
嵌入式操作系统Linux
实验报告
专业:
计算机科学与技术
班级:
13419011
学号:
1341901124
姓名:
武易
组员:
朱清宇
实验一Linux下进程的创建
一实验目的
1.掌握Linux下进程的创建及退出操作
2.了解fork、execl、wait、waitpid及之间的关系
二实验内容
创建进程,利用fork函数创建子进程,使其调用execl函数,退出进程后调用wait或waitpid清理进程。
三实验过程
1.进程的创建
许多进程可以并发的运行同一程序,这些进程共享内存中程序正文的单一副本,但每个进程有自己的单独的数据和堆栈区。
一个进程可以在任何时刻可以执行新的程序,并且在它的生命周期中可以运行几个程序;又如,只要用户输入一条命令,shell进程就创建一个新进程。
fork函数用于在进程中创建一个新进程,新进程是子进程。
原型如下:
#include /* 提供类型pid_t的定义 */
#include /* 提供函数的定义 */
pid_t fork(void);
使用fork函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间
fork系统调用为父子进程返回不同的值,fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
✓在父进程中,fork返回新创建子进程的进程ID;
✓在子进程中,fork返回0;
✓如果出现错误,fork返回一个负值;
用fork创建子进程后执行的是和父进程相同的程序,子进程可以通过调用exec函数以执行另一个程序。
当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程(例如其main函数)开始执行。
调用exec并不创建新进程,进程ID并未改变,只是用另一个新程序替换了当前进程的正文、数据、堆和栈段。
exec函数原型
execl,execlp,execle,execv,execve和execvp
2.进程的退出
一个进程正常终止有三种方式:
由main()函数返回;
调用exit()函数;
调用_exit()或_Exit()函数。
#include
#include
exit:
voidexit(intstatus)
_exit:
void_exit(intstatus)
3.wait和waitpid
一个进程调用了exit之后,该进程并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构。
在Linux进程的5种状态中,僵尸进程是非常特殊的一种,它已经放弃了几乎所有内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态等信息供其他进程收集。
如果一个进程已经终止,但是它的父进程尚未调用wait或waitpid对它进行清理,这时的进程状态称为僵尸(Zombie)进程。
该类进程保留了一定的信息(包括pID,退出状态,运行时间等),需要父进程通过wait/waitpid来取时才释放。
如果父进程不调用wait/waitpid的话,那么保留的那段信息就不会释放,其进程号就会一直被占用,如果系统大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程。
父进程通过wait和waitpid等函数等待子进程结束,这会导致父进程挂起。
也可以杀死父进程,则Zombie子进程会自动由init进程托管(init会负责清理)。
四实验代码
#include
intmain()
{
inti;
for(i=3;i>0;i--)
{
printf("Thisisthechild\n");
sleep
(2);
}
return0;
}
#include
#include
#include
#include
#include
intmain()
{
pid_tpid,pid_w;
pid=fork();
if(pid<0)
{
perror("forkfailed");
exit
(1);
}
if(pid==0)
{
execl("./chpro","chpro",NULL);
}
else{
do{
pid_w=waitpid(pid,NULL,WNOHANG);
if(pid_w==0){
printf("childprocesshasnoexited\n");
sleep
(1);
}
}while(pid_w==0);
if(pid_w==pid)
printf("Getchild%d\n",pid_w);
else
printf("someerroroccured.\n");
}
return0;
}
五实验结果
实验二Linux下shell程序设计
一实验目的
掌握Linux下shell程序的设计方法,脚本文件的编写方法
二实验内容
1.给shell脚本加注释,说明其功能
2.编写一个安装脚本文件,将某个已知的程序安装在/myprogram下
三实验代码
注释shell
#定义两个变量
PREFIX=uptech
TARGETDIR=/arm2410s
clear
#makeneededdirectory
if[-f$TARGETDIR/img/zImage];then
echo"Thetargetdirisalreadyexist!
"
echo"Pleasebackupyourfilesorchangetoanotherdirectory"
exit
fi
mkdir$TARGETDIR2>/dev/null
#初始化arm4l的开发工具
inst_armv4l_gcc(){
echo"installarmv4l-unknown-linux-gcc-2.95.2andlibraray..."
#解包
tar-xjfarmv4l-tools-2.95.2.tar.bz2-C/
}
#安装linux系统及文件系统
inst_linux(){
echo"installlinux-2.4..."
tar-xjf${PREFIX}-kernel.tar.bz2-C$TARGETDIR||exit
echo"installbusybox-1.00-pre10..."
tar-xjf${PREFIX}-busybox-1.00-pre10.tar.bz2-C$TARGETDIR||exit
echo"installrootfs..."
tar-xjf${PREFIX}-root.tar.bz2-C$TARGETDIR||exit
}
#gdb调试器初始化
inst_gdb(){
echo"installgdb&gdbserverforarm920t..."
cp-arfgdb$TARGETDIR||exit
tar-xjfgdb/insight-6.0.tar.bz2-C$TARGETDIR||exit
}
配置exp文件
inst_exp(){
echo"installexamplesprograms..."
cp-arfexp$TARGETDIR||exit
cp-arfdoc$TARGETDIR||exit
}
#初始化GUI程序
inst_gui(){
echo"installguiprograms"
cp-rafmicrowindows$TARGETDIR||exit
mkdir$TARGETDIR/minigui2>/dev/null
tar-jxfminigui/basic.tar.bz2-C$TARGETDIR/minigui
tar-jxfminigui/lib.tar.bz2-C$TARGETDIR/minigui
tar-jxfminigui/mde-1.6.0.tar.bz2-C$TARGETDIR/minigui
tar-jxfminigui/mg-samples-1.6.0.tar.bz2-C$TARGETDIR/minigui
tar-jxfminigui/res-host.tar.bz2-C$TARGETDIR/minigui
tar-jxfminigui/res-target.tar.bz2-C$TARGETDIR/minigui
}
#初始化配置文件
inst_config_file(){
#if[-f/root/.bash_profile];then\#如果/root/.bash_profile文件存在
#echo"backupold.bash_profileto.bash_profile_bak"
#cp-f/root/.bash_profile/root/.bash_profile.bak
#fi
#echo"copy.bash_profileto/root"
#cp-af.bash_profile/root/.bash_profile
if[-f/etc/minirc.dfl];then\#如果/etc/minirc.dfl文件存在
echo"backup/etc/minirc.df1."
cp-f/etc/minirc.dfl/etc/minirc.dfl.bak
fi
echo"copyminirc.df1to/etc"
cp-afminirc.dfl/etc/minirc.dfl
}
#............................
cdarmv4l-tools||exit
inst_armv4l_gcc
cd..
cddevelop||exit
inst_linux
inst_config_file
cd..
cp-arfsh$TARGETDIR
cp-arfimg$TARGETDIR
mkdir$TARGETDIR/demos
cdimg
tarjxfyaffs.tar.bz2-C$TARGETDIR/demos/2>/dev/null
cd..
inst_gdb
inst_exp
cdgui
inst_gui
cd..
cd$TARGETDIR
echoarm-linuxdevelopenviromentforUP-Netarm2410installcompleted!
Mysql-5.5.50-linux2.6-x86_64.tar.gz的安装:
#!
/bin/bash
MYSQL_HOME=/myprogram/mysql
#将你的mysql安装程序解压后的文件名设置为MYSQL_DIR,将安装程序(mysql-xxx.tar.gz)放到当前目录
MYSQL_DIR=mysql-5.5.50-linux2.6-x86_64
MYSQL_DIR_OLD=$PWD/${MYSQL_DIR}
MYSQL_DIR_NEW=/myprogram/${MYSQL_DIR}
MYSQL_SOURCE=$MYSQL_DIR_OLD.tar.gz
if[!
-f${MYSQL_SOURCE}]
then
echo"MySQLpackagenotfound!
"
exit1
fi
idmysql>/dev/null2>&1
if[$?
-eq1]
then
#Ifusermysqldoesnotexist,
#deletegroupmysqlfisrtifexists
sed-i'/^mysql/d'/etc/group
echo"Addgroupmysql"
groupaddmysql
echo"Addusermysql"
useradd-gmysqlmysql
fi
echo"UnzipMySQL-5.5.50"
tarzxvf${MYSQL_SOURCE}>/dev/null2>&1
echo"MoveMySQLtotherightplace"
mv${MYSQL_DIR_OLD}${MYSQL_DIR_NEW}
echo"Createmysqllinkage"
ln-s${MYSQL_DIR_NEW}${MYSQL_HOME}
echo"Changemysqldirectorytotherightuserandgroup"
cd$MYSQL_HOME
chown-Rmysql.
cd$MYSQL_HOME
chgrp-Rmysql.
echo"Createmysqlsystemdatabase"
${MYSQL_HOME}/scripts/mysql_install_db--user=mysql>/dev/null
cd$MYSQL_HOME
chown-Rmysqldata
cd$MYSQL_HOME
chown-Rroot.
echo"SetenvironmentPATH"
sed-i'/exportPATH=\/myprogram\/mysql\/bin:
$PATH/d'/etc/profile
echo'exportPATH=/myprogram/mysql/bin:
$PATH'>>/etc/profile
./etc/profile
echo"Setmysqlassystemservice"
cp$MYSQL_HOME/support-files/mysql.server/etc/init.d/mysql
sysv-rc-confmysqlon
/etc/init.d/mysqlstart
echo-n"Pleaseinputpasswordofmysqluserroot:
"
stty-echo
readROOT_PASSWORD
sttyecho
echo
if[-z$ROOT_PASSWORD]
then
echo"ERROR:
Thepasswordisnull!
"
exit1
fi
mysqladmin-urootpassword"$ROOT_PASSWORD"
mysql-uroot-p$ROOT_PASSWORD-e"grantallon*.*toroot@localhostidentifiedby'$ROOT_PASSWORD'"
if[$?
-eq0]
then
echo"Setmysqluserrootpasswordsuccessfully!
"
fi
四实验结果
实验三Linux下多线程程序设计
一实验目的
了解多线程程序设计的基本原理。
学习pthread库函数的使用。
二实验内容
读懂pthread.c的源代码,熟悉几个重要的PTHREAD库函数的使用。
掌握共享锁和信号量的使用方法。
进入/arm2410cl/exp/basic/02_pthread目录,运行make产生pthread程序,使用NFS方式连接开发主机进行运行实验。
三实验过程
1.多线程程序的优缺点
多线程程序作为一种多任务、并发的工作方式,有以下的优点:
1)提高应用程序响应。
这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(timeconsuming)置于一个新的线程,可以避免这种尴尬的情况。
2)使多CPU系统更加有效。
操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
3)改善程序结构。
一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。
LIBC中的pthread库提供了大量的API函数,为用户编写应用程序提供支持。
2.实验源代码与结构流程图本实验为著名的生产者-消费者问题模型的实现,主程序中分别启动生产者线程和消费者线程。
生产者线程不断顺序地将0到1000的数字写入共享的循环缓冲区,同时消费者线程不断地从共享的循环缓冲区读取数据。
流程图如图所示:
1、阅读源代码及编译应用程序
进入exp/basic/02_pthread目录,使用vi编辑器或其他编辑器阅读理解源代码。
运行make产生pthread可执行文件,如图所示。
2、下载和调试
运行可执行程序,观察运行结果的正确性。
四实验代码
#include
#include
#include
//#include
#include"pthread.h"
#defineBUFFER_SIZE16
/*设置一个整数的圆形缓冲区*/
structprodcons{
/*缓冲区数组*/
intbuffer[BUFFER_SIZE];
pthread_mutex_tlock;/*互斥锁*/
intreadpos,writepos;/*读写的位置*/
/*缓冲区非空信号*/
pthread_cond_tnotempty;
/*缓冲区非满信号*/
pthread_cond_tnotfull;
};
/*--------------------------------------------------------*/
/*初始化缓冲区*/
voidinit(structprodcons*b)
{
pthread_mutex_init(&b->lock,NULL);
pthread_cond_init(&b->notempty,NULL);
pthread_cond_init(&b->notfull,NULL);
b->readpos=0;
b->writepos=0;
}
/*--------------------------------------------------------*/
/*向缓冲区中写入一个整数*/
voidput(structprodcons*b,intdata)
{
pthread_mutex_lock(&b->lock);
/*等待缓冲区非满*/
while((b->writepos+1)%BUFFER_SIZE==b->readpos){
printf("waitfornotfull\n");
pthread_cond_wait(&b->notfull,&b->lock);
}
/*写数据并且指针前移*/
b->buffer[b->writepos]=data;
b->writepos++;
if(b->writepos>=BUFFER_SIZE)b->writepos=0;
/*设置缓冲区非空信号*/
pthread_cond_signal(&b->notempty);
pthread_mutex_unlock(&b->lock);
}
/*--------------------------------------------------------*/
/*从缓冲区中读出一个整数*/
intget(structprodcons*b)
{
intdata;
pthread_mutex_lock(&b->lock);
/*等待缓冲区非空*/
while(b->writepos==b->readpos){
printf("waitfornotempty\n");
pthread_cond_wait(&b->notempty,&b->lock);
}
/*读数据并且指针前移*/
data=b->buffer[b->readpos];
b->readpos++;
if(b->readpos>=BUFFER_SIZE)b->readpos=0;
/*设置缓冲区非满信号*/
pthread_cond_signal(&b->notfull);
pthread_mutex_unlock(&b->lock);
returndata;
}
/*--------------------------------------------------------*/
#defineOVER(-1)
#defineENDMINITERM27
/*ESCtoquitminiterm*/
structprodconsbuffer;
intstop=0;
intend=0;
/*--------------------------------------------------------*/
void*producer(void*data)
{
intn;
for(n=0;n<1000;n++){
if(stop)
break;
printf("put-->%d\n",n);
put(&buffer,n);
sleep
(1);
}
put(&buffer,OVER);
printf("producerstopped!
\n");
end=1;
returnNULL;
}
/*--------------------------------------------------------*/
void*consumer(void*data)
{
intd;
while
(1){
if(stop)
break;
d=get(&buffer);
if(d==OVER)break;
printf("%d-->get\n",d