资源描述
一、Shell编程 要求:写出两个Shell程序,每个程序不少于十五行;说明程序主要功能;每行给出注释。
#Major Function:simple calculator for + - # /
#
#Time :Sunday May 5,2013
#
#copyright :
#!/bin/bash
#!/bin/sh
main()
{
echo "calculator V1.0"
# 选择操作方式 help or calulate or exit
while [ 1 ]
do
read select
if [ "$select" = "help" ]
then
echo "1 calculator"
echo "0 exit"
elif [ "$select" = "1" ]
then
cal;
elif [ "$select" = "0" ]
then
break;
fi
done
}
cal()
{
read str
# 针对读入的字串,提取操作数及操作符
num1=`echo $str|cut -d' ' -f1`
num2=`echo $str|cut -d' ' -f3`
sign=`echo $str|cut -d' ' -f2`
# 根据sign选择对应操作 + - # /
case $sign in
+)
sum=`expr $num1 + $num2`;
echo "$num1 $sign $num2 = $sum";;
-)
sum=`expr $num1 - $num2`;
echo "$num1 $sign $num2 = $sum";;
\#)
sum=`expr $num1 \* $num2`;
echo "$num1 * $num2 = $sum";;
/)
sum=`expr $num1 / $num2`;
echo "$num1 $sign $num2 = $sum";;
esac
}
main
#!/bin/bash
# 数字游戏
random ()
{
FLOOR=0
RANGE=10
num=0
while [ $num -le $FLOOR ]
do
num=$RANDOM
#通过使随机数成为指定范围的随机数
let "num %= $RANGE"
done
# echo "Random number between $FLOOR and $RANGE --- $number"
return
}
random
########################
D1=$num
random
D2=$num
while [ $D2 == $D1 ]
do random
D2=$num
done
random
D3=$num
while [ $D3 == $D2 ]||[ $D3 == $D1 ]
do random
D3=$num
done
random
D4=$num
while [ $D4 == $D3 ]||[ $D4 == $D2 ]||[ $D4 == $D1 ]
do random
D4=$num
done
#echo $D1 $D2 $D3 $D4 ######### This is for test
input_num ()
{
#输入四个数据 并判断比较对错情况 返回?A?B
echo
echo "Please input four different numbers between 1~9 ( Just like this \"5 2 1 4\" ) "
read S1 S2 S3 S4
}
zero ()
{
while [ $S1 == 0 ]|| [ $S2 == 0 ]||[ $S3 == 0 ]||[ $S4 == 0 ]
do echo "zero is not allowd"
input_num
done
}
input_num
zero
while [ $S1 == $S2 ]||[ $S1 == $S3 ]||[ $S1 == $S4 ]||[ $S2 == $S3 ]||[ $S2 == $S4 ]||[ $S3 == $S4 ]
do echo "wrong input"
input_num
done
echo $S1 $S2 $S3 $S4
declare A
declare B
# 比较函数
compare ()
{
A=0
B=0
if [ $S1 == $D1 ]
then let A=$A+1
elif [ $S1 == $D2 ]||[ $S1 == $D3 ]||[ $S1 == $D4 ]
then let B=$B+1
fi
if [ $S2 == $D2 ]
then let A=$A+1
elif [ $S2 == $D1 ]||[ $S2 == $D3 ]||[ $S2 == $D4 ]
then let B=$B+1
fi
if [ $S3 == $D3 ]
then let A=$A+1
elif [ $S3 == $D1 ]||[ $S3 == $D2 ]||[ $S3 == $D4 ]
then let B=$B+1
fi
if [ $S4 == $D4 ]
then let A=$A+1
elif [ $S4 == $D1 ]||[ $S4 == $D2 ]||[ $S4 == $D3 ]
then let B=$B+1
fi
clear
echo "$S1 $S2 $S3 $S4 $A"A" $B"B" ">>~/answ.txt
/bin/cat ~/answ.txt
while [ $A -lt 4 ]
do input_num
compare
done
if [ $A == 4 ]
then echo " Congratulation, you are very good "
fi
return
}
compare
二、Linux操作系统配置实例 要求:查阅资料结合实际使用情况,写出Linux操作系统使用中的一个配置的详细过程;具体配
置目标不限(自选)。
1、Linux下安装MySQL需要下面两个文件:MySQL-server-5.1.7-0.i386.rpm mysql
2、Linux下安装MySQL
rpm文件是Red Hat公 司开发的软件安装包,rpm可让Linux在安装软件包时免除许多复杂的手续。该命令在安装时常用的参数是 –ivh ,其中i表示将安装指定的rmp软件包,V表示安装时的详细信息,h表示在安装期间出现“#”符号来显示目前的安装过程。这个符号将持续到安装完成后才停 止。
1)安装服务器端
在有两个rmp文件的目录下运行如下命令:
[root@test1 local]# rpm -ivh MySQL-server-5.1.7-0.i386.rpm MySQL-client-5.1.7-0.i386.rpm
显示如下信息。
warning: MySQL-server-5.1.7-0.i386.rpm
signature: NOKEY, key ID 5072e1f5
Preparing... ########################################### [100%]
1:MySQL-server ########################################### [100%]
。。。。。。(省略显示)
/usr/bin/mysqladmin -u root password 'new-password'
/usr/bin/mysqladmin -u root -h test1 password 'new-password'
。。。。。。(省略显示)
Starting mysqld daemon with databases from /var/lib/mysql
如出现如上信息,服务端安装完毕。测试是否成功可运行netstat看Mysql端口是否打开,如打开表示服务已经启动,安装成功。Mysql默认的端口是3306。
[root@test1 local]# netstat -nat
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN
上面显示可以看出MySQL服务已经启动。
2)安装客户端
运行如下命令:
[root@test1 local]# rpm -ivh MySQL-client-5.1.7-0.i386.rpm
warning: MySQL-client-5.1.7-0.i386.rpm: V3 DSA signature: NOKEY, key ID 5072e1f5
Preparing... ########################################### [100%]
1:MySQL-client ########################################### [100%]
显示安装完毕。
用下面的命令连接mysql,测试是否成功。
3、登录MySQL
登录MySQL的命令是mysql, mysql 的使用语法如下:
mysql [-u username] [-h host] [-p[password]] [dbname]
username 与 password 分别是 MySQL 的用户名与密码,mysql的初始管理帐号是root,没有密码,注意:这个root用户不是Linux的系统用户。MySQL默认用户是root,由于 初始没有密码,第一次进时只需键入mysql即可。
[root@test1 local]# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 4.0.16-standard
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
出现了“mysql>”提示符,恭喜你,安装成功!
增加了密码后的登录格式如下:
mysql -u root -p
Enter password: (输入密码)
其中-u后跟的是用户名,-p要求输入密码,回车后在输入密码处输入密码。
注意:这个mysql文件在/usr/bin目录下,与后面讲的启动文件/etc/init.d/mysql不是一个文件。
三、Linux操作系统应用开发实例 要求:编写Linux下的一个应用程序。开发语言和工具不限;给出源代码和运行结果。关键代码部分要给出注释。
通过
Tcpserver
class TcpServer : public QDialog
{
Q_OBJECT
public:
explicit TcpServer(QWidget *parent = 0);
~TcpServer();
void refused();
void initServer();
protected:
void changeEvent(QEvent *e);
private:
Ui::TcpServer *ui;
qint16 tcpPort;
QTcpServer *tcpServer;
QString fileName;
QString theFileName;
QFile *localFile;
qint64 TotalBytes;
qint64 bytesWritten;
qint64 bytesToWrite;
qint64 loadSize;
QByteArray outBlock;//缓存一次发送的数据
QTcpSocket *clientConnection;
QTime time;//计时器
private slots:
void on_serverSendBtn_clicked();
void on_serverCloseBtn_clicked();
void on_serverOpenBtn_clicked();
void sendMessage();
void updateClientProgress(qint64 numBytes);
signals:
void sendFileName(QString fileName);
};
Tcp client
class TcpClient : public QDialog
{
Q_OBJECT
public:
explicit TcpClient(QWidget *parent = 0);
~TcpClient();
void setHostAddress(QHostAddress address);
void setFileName(QString fileName){localFile = new QFile(fileName);}
protected:
void changeEvent(QEvent *e);
private:
Ui::TcpClient *ui;
QTcpSocket *tcpClient;
quint16 blockSize;
QHostAddress hostAddress;
qint16 tcpPort;
qint64 TotalBytes;
qint64 bytesReceived;
qint64 bytesToReceive;
qint64 fileNameSize;
QString fileName;
QFile *localFile;
QByteArray inBlock;
QTime time;
private slots:
void on_tcpClientCancleBtn_clicked();
void on_tcpClientCloseBtn_clicked();
void newConnect();
void readMessage();
void displayError(QAbstractSocket::SocketError);
};
实现:
chat::chat(QString pasvusername, QString pasvuserip) : ui(new Ui::chat)
{
ui->setupUi(this);
ui->textEdit->setFocusPolicy(Qt::StrongFocus);
ui->textBrowser->setFocusPolicy(Qt::NoFocus);
ui->textEdit->setFocus();
ui->textEdit->installEventFilter(this);
a = 0;
is_opened = false;
// this->is_opened = false;
xpasvusername = pasvusername;
xpasvuserip = pasvuserip;
ui->label->setText(tr("与%1聊天中 对方IP:%2").arg(xpasvusername).arg(pasvuserip));
//UDP部分
xchat = new QUdpSocket(this);
xport = 45456;
// xchat->bind(xport, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
xchat->bind( QHostAddress::QHostAddress(getIP()), xport );
connect(xchat, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));
//TCP部分
server = new TcpServer(this);
connect(server,SIGNAL(sendFileName(QString)),this,SLOT(sentFileName(QString)));
connect(ui->textEdit,SIGNAL(currentCharFormatChanged(QTextCharFormat)),this,SLOT(currentFormatChanged(const QTextCharFormat)));
}
chat::~chat()
{
is_opened = false;
delete ui;
}
bool chat::eventFilter(QObject *target, QEvent *event)
{
if(target == ui->textEdit)
{
if(event->type() == QEvent::KeyPress)//按下键盘某键
{
QKeyEvent *k = static_cast<QKeyEvent *>(event);
if(k->key() == Qt::Key_Return)//回车键
{
on_send_clicked();
return true;
}
}
}
return QWidget::eventFilter(target,event);
}
//处理用户离开
void chat::participantLeft(QString userName,QString localHostName,QString time)
{
ui->textBrowser->setTextColor(Qt::gray);
ui->textBrowser->setCurrentFont(QFont("Times New Roman",10));
ui->textBrowser->append(tr("%1 于 %2 离开!").arg(userName).arg(time));
}
QString chat::getUserName() //获取用户名
{
QStringList envVariables;
envVariables << "USERNAME.*" << "USER.*" << "USERDOMAIN.*"
<< "HOSTNAME.*" << "DOMAINNAME.*";
QStringList environment = QProcess::systemEnvironment();
foreach (QString string, envVariables)
{
int index = environment.indexOf(QRegExp(string));
if (index != -1)
{
QStringList stringList = environment.at(index).split('=');
if (stringList.size() == 2)
{
return stringList.at(1);
break;
}
}
}
return false;
}
QString chat::getIP() //获取ip地址
{
QList<QHostAddress> list = QNetworkInterface::allAddresses();
foreach (QHostAddress address, list)
{
if(address.protocol() == QAbstractSocket::IPv4Protocol) //我们使用IPv4地址
return address.toString();
}
return 0;
}
void chat::hasPendingFile(QString userName,QString serverAddress, //接收文件
QString clientAddress,QString fileName)
{
QString ipAddress = getIP();
if(ipAddress == clientAddress)
{
int btn = QMessageBox::information(this,tr("接受文件"),
tr("来自%1(%2)的文件:%3,是否接收?")
.arg(userName).arg(serverAddress).arg(fileName),
QMessageBox::Yes,QMessageBox::No);
if(btn == QMessageBox::Yes)
{
QString name = QFileDialog::getSaveFileName(0,tr("保存文件"),fileName);
if(!name.isEmpty())
{
TcpClient *client = new TcpClient(this);
client->setFileName(name);
client->setHostAddress(QHostAddress(serverAddress));
client->show();
}
}
else{
sendMessage(Refuse,serverAddress);
}
}
}
以上是主要源码 未包含局域网广播ip列表获取及udp实现部分
四、 linux内核源码解读
Linux信号机制
1.信号的来源
程序错误:除零,非法内存访问…
外部信号:终端Ctrl-C产生SGINT信号,定时器到期产生SIGALRM…
显式请求:kill函数允许进程发送任何信号给其他进程或进程组。
2.Linux下查看信号
在Linux下,可以通过以下命令查看系统所有的信号:
kill -l
可以通过类似下面的命令显式的给一个进程发送一个信号:
kill -2 pid
3.信号的处理
忽略信号:大部分信号可被忽略,除SIGSTOP和SIGKILL信号外(这是超级用户杀掉或停掉任意进程的手段)。
捕获信号:注册信号处理函数,它对产生的特定信号做处理。
让信号默认动作起作用:unix内核定义的默认动作,有5种情况:
a) abort:终止进程并产生core文件。
b) stop:终止进程但不生成core文件。
c) 忽略:忽略信号。
d) suspend:挂起进程。
e) continue:若进程是挂起的,则resume进程,否则忽略此信号。
二、深入信号机制内部
1.信号检测和响应的时机
当前进程由于系统调用、中断或异常而进入内核态以后,从内核态返回到用户态之前。
当前进程在内核中进入睡眠以后刚被唤醒的时候(必定是在系统调用中),或者由于不可忽略信号的存在而提前返回到用户空间。
2.Linux 0.11中用于信号处理的数据结构
用于保存信号信息的结构体
[cpp] view plaincopy
1 struct sigaction {
2 void (*sa_handler)(int);//信号处理句柄
3 sigset_t sa_mask;//信号的屏蔽码,可以阻塞指定的信号
4 int sa_flags;//信号选项标志
5 void (*sa_restorer)(void);//信号恢复函数指针(系统内部使用)
6 };
进程结构体重关于信号的定义
[cpp] view plaincopy
7 long signal;
8 struct sigaction sigaction[32];
9 long blocked; /* bitmap of masked signals */
3.信号的预处理操作
do_signal()函数 参数为内核态堆栈中的内容
[cpp] view plaincopy
10 void do_signal(long signr,long eax, long ebx, long ecx, long edx,
11 long fs, long es, long ds,
12 long eip, long cs, long eflags,
13 unsigned long * esp, long ss)
14 {
15 unsigned long sa_handler;
16 long old_eip=eip;
17 struct sigaction * sa = current->sigaction + signr - 1;
18 int longs;
19 unsigned long * tmp_esp;
20
21 sa_handler = (unsigned long) sa->sa_handler;
22 if (sa_handler==1)
23 return;
24 if (!sa_handler) {
25 if (signr==SIGCHLD)
26 return;
27 else
28 do_exit(1<<(signr-1));
29 }
30 if (sa->sa_flags & SA_ONESHOT)
31 sa->sa_handler = NULL;
32 *(&eip) = sa_handler;
33 longs = (sa->sa_flags & SA_NOMASK)?7:8;
34 *(&esp) -= longs;
35 verify_area(esp,longs*4);
36 tmp_esp=esp;
37 put_fs_long((long) sa->sa_restorer,tmp_esp++);
38 put_fs_long(signr,tmp_esp++);
39 if (!(sa->sa_flags & SA_NOMASK))
40 put_fs_long(current->blocked,tmp_esp++);
41 put_fs_long(eax,tmp_esp++);
42 put_fs_long(ecx,tmp_esp++);
43 put_fs_long(edx,tmp_esp++);
44 put_fs_long(eflags,tmp_esp++);
45 put_fs_long(old_eip,tmp_esp++);
46 current->blocked |= sa->sa_mask;
47 }
对内核态堆栈的修改
4.操作系统进入信号处理
通过上述内容,可以看到操作系统在检测到有信号传入时,首先把内核堆栈中存放返回执行点的eip(指令寄存器)保存为old_eip,然后将eip替换为信号处理函数的地址,然后将内核中保存的“原ESP”(即用户态栈地址)减去一定的值,目的是扩大用户态的栈,然后将内核栈上的内容保存到用户栈上。
之所以把EIP的值设置成信号处理函数的地址,是因为一旦进程返回用户态,就要去执行信号处理程序,所以EIP要指向信号处理程序而不是原来应该执行的地址。
5.操作系统退出信号处理
在前面介绍sigaction数据结构的时候出现了信号活动恢复函数指针sa_restroer,该指针主要用于用户态堆栈的清理,把系统调用后的返回值eax和寄存器ecx,edx以及标志寄存器eflags弹出,完全恢复系统调用后各寄存器和CPU的状态,最后通过ret指令弹出原用户程序的eip(即堆栈中的old_eip),返回执行用户程序。
但是在Linux内核代码中,并没有 给出此函数的具体定义,查看相关资料,在Linux的Libc函数库中定义有函数如下
编译程序在编译连接用户自定义的信号处理函数时,会将sa_restorer()函数插入到用户程序中。这样,用户在处理完自定义的信号处理函数后,就会继续执行用户代码了。
Liunx结课作业
高源成
1067111220
10计2班
展开阅读全文