Linux的进程线程.docx
《Linux的进程线程.docx》由会员分享,可在线阅读,更多相关《Linux的进程线程.docx(13页珍藏版)》请在冰豆网上搜索。
Linux的进程线程
实验五Linux的进程/线程
2012学年—2013学年第二学期Linux应用实验报告书
专业名称班级:
姓名:
学号:
实验题目:
实验五Linux的进程/线程
实验环境:
RedHatLinux9
实验目的:
通过编写多进程程序,熟练掌握fork、exec、wait、waitpid等函数的使用,进一步理解Linux多进程编程。
通过编写经典的“生产者消费者”问题的实验,可以进一步熟悉Linux多线程编程,并且掌握用信号量处理线程间的同步互斥问题。
实验内容:
1)有3个进程,其中一个为父进程,其余两个是该父进程创建的子进程,其中一个子进程运行“ls-l”指令,另一个子进程在暂停5s之后异常退出,父进程并不阻塞自己,并等待子进程的退出信息,待收集到该信息,父进程就返回。
实验过程:
运行结果:
在Linux中创建一个新进程的唯一方法是使用fork函数,fork()执行一次但有两个返回值。
在父进程中,返回值是子进程的进程号;在子进程中,返回值为0。
因此可通过返回值来判断当前进程是父进程还是子进程。
使用fork函数得到的子进程是父进程的一个复制品,它从父进程处复制了整个进程的地址空间,包括进程上下文,进程堆栈,内存信息,打开的文件描述符,信号控制设定,进程优先级,进程组号,当前工作目录,根目录,资源限制,控制终端等。
而子进程所独有的只是它的进程号,资源使用和计时器等。
可以看出,使用fork函数的代价是很大的,它复制了父进程中的代码段,数据段和堆栈段里的大部分内容,使得fork函数的执行速度并不快。
2)
Ø将上述程序编译运行,并观察(注意父子进程关系),特别是在第二个进程退出后,第3,4两个进程。
必要的话,可以加大各个子进程的睡眠时间。
运行结果:
3)“生产者/消费者”问题描述:
有一个有限缓冲区和两个线程:
生产者和消费者。
他们分别把产品放入缓冲区和从缓冲区中拿走产品。
当一个生产者在缓冲区满时必须等待,当一个消费者在缓冲区空时也必须等待。
structmsg{
structmsg*next;
intnum;};
试用信号量(Semaphore)改写。
信号量的考虑:
这里使用3个信号量,其中两个信号量avail和full分别用于解决生产者和消费者线程之间的同步问题,mutex是用于这两个线程之间的互斥问题。
其中avail初始化N(有界缓冲区的空单元数),mutex初始化为1,full初始化为0。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineFIFO"myfifo"
#defineN5
intlock_var;
time_tend_time;
charbuf_r[100];
sem_tmutex,full,avail;
intfd;
voidpthread1(void*arg);
voidpthread2(void*arg);
voidproductor(void*arg);
voidconsumer(void*arg);
intmain(intargc,char*argv[])
{
pthread_tid1,id2;
pthread_tmon_th_id;
intret;
end_time=time(NULL)+30;
/*创建有名管道*/
if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!
=EEXIST))
printf("cannotcreatefifoserver\n");
printf("Preparingforreadingbytes...\n");
memset(buf_r,0,sizeof(buf_r));
/*打开管道*/
fd=open(FIFO,O_RDWR|O_NONBLOCK,0);
if(fd==-1)
{
perror("openerror!
\n");
exit
(1);
}
/*初始化互斥信号量1*/
ret=sem_init(&mutex,0,3);
/*初始化avail信号量为N*/
ret=sem_init(&avail,0,N);
/*初始化full信号量为0*/
ret=sem_init(&full,0,0);
if(ret!
=0)
{
perror("sem_initerror\n");
}
/*创建两个线程*/
/*ret=pthread_create(&id2,NULL,(void*)consumer,NULL);
if(ret!
=0)
perror("pthreadcreate2\n");*/
printf("midpthread\n");
ret=pthread_create(&id1,NULL,(void*)productor,NULL);
if(ret!
=0)
perror("pthreadcreate1\n");
ret=pthread_create(&id2,NULL,(void*)consumer,NULL);
if(ret!
=0)
perror("pthreadcreate2\n");
pthread_join(id1,NULL);
pthread_join(id2,NULL);
exit(0);
}
/*生产者线程*/
voidproductor(void*arg)
{
inti,nwrite;
while(time(NULL) {
/*P操作信号量avail和mutex*/
sem_wait(&avail);
sem_wait(&mutex);
/*生产者写入数据*/
if((nwrite=write(fd,"hello",5))==-1)
{
if(errno==EAGAIN)
printf("TheFIFOhasnotbeenreadyet.Pleasetrylater\n");
}
else
printf("writehellototheFIFO\n");
/*V操作信号量full和mutex*/
sem_post(&full);
sem_post(&mutex);
sleep
(1);
}
}
/*消费者线程*/
voidconsumer(void*arg)
{
intnolock=0;
intret,nread;
while(time(NULL) {
/*P操作信号量full和mutex*/
sem_wait(&full);
sem_wait(&mutex);
memset(buf_r,0,sizeof(buf_r));
if((nread=read(fd,buf_r,100))==1)
{
if(errno==EAGAIN)
printf("nodatayet\n");
}
printf("read%sfromFIFO\n",buf_r);
sem_post(&avail);
sem_post(&mutex);
sleep
(1);
}
}