11计科4嵌入式linux高级编程实验1114 1.docx
《11计科4嵌入式linux高级编程实验1114 1.docx》由会员分享,可在线阅读,更多相关《11计科4嵌入式linux高级编程实验1114 1.docx(13页珍藏版)》请在冰豆网上搜索。
11计科4嵌入式linux高级编程实验11141
注意
实验的名称为
1文件的基本操作
2文件的定位与控制
3目录文件的操作
4进程和进程的同步
5守护进程与管道
6消息队列与共享内存IPC
7线程与线程互斥
8线程同步中的信号量
9简单的网络通信
10IP层通信
11基于链路层的通信
12多进程并发通信和多线程并发通信
13信号编程
14时间与定时器编程
要交电子档的程序是:
1《实验8线程同步中的信号量》中第一个程序生产者与消费者名称为procom.c
2《实验10IP层通信》中第2个程序模拟ping的程序
3《实验12多进程并发通信和多线程并发通信》中第2个程序多线程并发通信
请将上述程序的源代码打成一个压缩文件,后缀为rar,文件名为学号+姓名例如
1260310032梁兰兰.rar
1260310037李晓燕.rar
然后将压缩文件以附件的形式发到b11class4@
请将邮件题目栏改为学号+姓名
实验11基于链路层的通信
1程序说明
程序一开始产生链路层原始套接字,然后将网卡设置为混杂模式。
利用recvfrom函数接收到buf缓冲中,利用analyze函数进行分析
关键代码如下:
1产生原始套接字
sock=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
2设置网卡为混杂模式
strcpy(ifr.ifr_name,"eth0");
ifr.ifr_flags=IFF_UP|IFF_PROMISC|IFF_BROADCAST|IFF_RUNNING;
intret=ioctl(sock,SIOCSIFFLAGS,&ifr);
3循环接收数据包,并且利用analyData进行分析
while
(1)
{
unsignedintrval=recvfrom(sock,buf,sizeof(buf),0,(structsockaddr*)&rcvaddr,&len);
analyData(buf);
}
2程序代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
intcount=0;
charbuf[16];
voidshowmac(chari)
{
//该函数负责格式化形式打印mac地址
charibuf[16];
if(i==0)printf("00");
sprintf(ibuf,"%x",i);
if(i<0)
{
intl=strlen(ibuf);
printf("%c",ibuf[l-2]);
printf("%c",ibuf[l-1]);
}
if(i>0&&i<16)
{
printf("0");
printf("%s",ibuf);
}
if(i>=16)printf("%s",ibuf);
}
intanalyData(char*data)
{
structiphdr*ip;
structtcphdr*tcp;
structether_header*ether;
char*dmac,*smac;
ether=(structether_header*)data;
printf("链路层数据包类型%d",ether->ether_type);
smac=(char*)ether;
dmac=smac+6;
intk;
for(k=0;k<6;k++)
{
showmac(dmac[k]);
printf("-");
}
printf("");
for(k=0;k<6;k++)
{
showmac(smac[k]);
printf("-");
}
printf("\r\n");
ip=(structiphdr*)(data+sizeof(structether_header));
count++;
printf("Protocol:
:
%d",ip->protocol);
printf("SourceIP:
:
%s",inet_ntoa(*((structin_addr*)&ip->saddr)));
printf("DestIP:
:
%s",inet_ntoa(*((structin_addr*)&ip->daddr)));
tcp=(structtcphdr*)(data+sizeof(structiphdr));
printf("sourceport=%ddestport=%d",htons(tcp->source),htons(tcp->dest));
printf("Alreadyget%dpackage\r\n",count);
printf("\n");
return1;
}
intmain(intargc,char**argv)
{charbuf[9216];
count=0;
intsock;
structsockaddr_inrcvaddr;
sock=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if(sock<0){printf("socketerror!
\r\n");exit(-1);};
printf("rawsocket%dcreatedsuccessful\r\n",sock);
structifreqifr;
strcpy(ifr.ifr_name,"eth0");
ifr.ifr_flags=IFF_UP|IFF_PROMISC|IFF_BROADCAST|IFF_RUNNING;
intret=ioctl(sock,SIOCSIFFLAGS,&ifr);
if(ret==-1){printf("setethtopromiscmodelfailed\r\n");exit(-1);};
intrecvbuf=9126;
setsockopt(sock,SOL_SOCKET,SO_RCVBUF,&recvbuf,sizeof(int));//扩大内核中的接收缓冲区的大小
while
(1)
{
intlen=sizeof(rcvaddr);
memset(buf,0,sizeof(buf));
unsignedintrval=recvfrom(sock,buf,sizeof(buf),0,(structsockaddr*)&rcvaddr,&len);
if(rval>0)
{
printf("get%dbytes\r\n",rval);
analyData(buf);
printf("\r\n");
}
}
}
实验12多进程并发通信和多线程并发通信
1多进程的并发通信程序如下
文件名server.c
#include
#include
#include
#include
#include
#include
#include
#definePORT82
#defineBUFSIZE512
charbuf[BUFSIZE+1];
intmain()
{
//第1步创建套接字
intsockfd=socket(AF_INET,SOCK_STREAM,0);
intopt=SO_REUSEADDR;
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));//端口重用
//第2步设置地址结构体
structsockaddr_insaddr,caddr;
saddr.sin_family=AF_INET;//使用internet协议
saddr.sin_port=htons(PORT);
inet_aton("0.0.0.0",&saddr.sin_addr);
//第3步绑定
bind(sockfd,(structsockaddr*)&saddr,sizeof(saddr));
//第4步监听
listen(sockfd,128);
while
(1)
{
intlen=sizeof(caddr);
intnew_fd=accept(sockfd,(structsockaddr*)&caddr,&len);//第5步接收
intret=fork();
if(ret!
=0)continue;
while
(1)
{
intn=read(new_fd,buf,sizeof(buf));
if(n==0)
{
printf("%s:
%dclose\r\n",inet_ntoa(caddr.sin_addr),htons(caddr.sin_port));
exit(0);
}
buf[n]=0;
printf("%sfrom%s:
%d\r\n",buf,inet_ntoa(caddr.sin_addr),htons(caddr.sin_port));
}
}
}
2多线程的并发通信程序如下
#include
#include
#include
#include
#include
#include
#include
#definePORT82
#defineBUFSIZE512
structARG
{
structsockaddr_incliaddr;
intsockfd;
};
charbuf[BUFSIZE+1];
void*fun(void*arg)
{
charip[64];
structARG*y=(structARG*)arg;
strcpy(ip,inet_ntoa(y->cliaddr.sin_addr));//取得传递过来的ip地址
intport=htons(y->cliaddr.sin_port);
intfd=y->sockfd;
while
(1)
{
intz=read(fd,buf,BUFSIZE);//第6步读取套接字
if(z==0){printf("client%s:
%dclose!
\r\n",ip,port);break;};
buf[z]='\0';
printf("%sfrom%s:
%d\r\n",buf,ip,port);//打印
}
close(fd);
pthread_exit(0);
}
intmain()
{
//第1步创建套接字
intsockfd=socket(AF_INET,SOCK_STREAM,0);
intopt=SO_REUSEADDR;
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));//端口重用
//第2步设置地址结构体
structsockaddr_insaddr,caddr;
saddr.sin_family=AF_INET;//使用internet协议
saddr.sin_port=htons(PORT);
inet_aton("0.0.0.0",&saddr.sin_addr);
//第3步绑定
bind(sockfd,(structsockaddr*)&saddr,sizeof(saddr));
//第4步监听
listen(sockfd,128);
while
(1)
{
intlen=sizeof(caddr);
intnew_fd=accept(sockfd,(structsockaddr*)&caddr,&len);//第5步接收
pthread_tp1;
structARGx;
x.sockfd=new_fd;//将new_fd复制到x中的sockfd中
memcpy(&x.cliaddr,&caddr,sizeof(caddr));//将caddr复制到参数x中的cliaddr中
pthread_create(&p1,NULL,fun,(void*)&x);
}
}
实验13信号编程
程序1用kill函数和raise函数
#include
#include
#include
#include
intmain()
{
intr=fork();
if(r==0)
{//子进程
raise(SIGSTOP);//子进程给自己发SIGSTOP信号
exit(0);
}
else
{//父进程
printf("子进程编号pid=%d\n",r);
if((waitpid(r,NULL,WNOHANG))==0)
{
getchar();
intk=kill(r,SIGKILL);//结束子进程
printf("k的返回取值为%d\n",k);
}
}
}
程序2用signal函数改变信号处理函数
#include
#include
#include
#include
inti;
voidfun(intsigno)
{
i++;
printf("第%d次ctrl+c\n",i);
if(i==10)exit(0);
}
intmain()
{
i=0;
signal(SIGINT,fun);
while
(1)
{
}
}
实验3用sigaction改变信号处理函数
#include
#include
voidWrkProcess(intnsig)
{
printf("WrkProcess.Igetsignal.%dthreadid:
%d/n",nsig,pthread_self());
inti=0;
while(i<5){
printf("%d/n",i);
sleep
(1);
i++;
}
}
intmain()
{
structsigactionact,oldact;
act.sa_handler=WrkProcess;
act.sa_flags=SA_NODEFER|SA_RESETHAND;
sigaction(SIGINT,&act,&oldact);
printf("mainthreadid:
%d/n",pthread_self());
while
(1)sleep(5);
return0;
}
实验14时间与定时器编程
实验1用alarm编程
1。
alarm()执行后,进程将继续执行,在后期(alarm以后)的执行过程中将会在seconds秒后收到信号SIGALRM并执行其处理函数。
#include
#include
#include
intn=0;
voidtimefunc(intsig)
{
printf("count:
%d",n++);
signal(SIGALRM,timefunc);
alarm
(1);
}
voidmian()
{
pid_tpid;
intstatus;
signal(SIGALRM,timefunc);
alarm
(1);
while
(1);
}
实验2用setitimer函数编程
setitimer()比alarm功能强大,支持3种类型的定时器:
其中ITIMER_REAL信号以系统真实的时间来计算,它送出SIGALRM信号。
下面的程序时间间隔为0.5秒,定时发送SIGPROF信号,进程受到信号后打印定时的次数,以中断结束。
#include
#include
#include
#include
#include
intn=0;
voidtimefunc(intsig)
{
printf("Count:
%d\n",n++);
signal(SIGPROF,timefunc);
}
intmain()
{
sturctitimervalvalue;
value.it_value.tv_sec=0;
value.it_value.tv_usec=500*1000;
value.it_interval.tv_sec=0;
value.it_interval.tv_usec=500*1000;
setitimer(ITIMER_PROF,&value,NULL);
while
(1);
}