processlab.docx

上传人:b****6 文档编号:8152555 上传时间:2023-01-29 格式:DOCX 页数:26 大小:32.64KB
下载 相关 举报
processlab.docx_第1页
第1页 / 共26页
processlab.docx_第2页
第2页 / 共26页
processlab.docx_第3页
第3页 / 共26页
processlab.docx_第4页
第4页 / 共26页
processlab.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

processlab.docx

《processlab.docx》由会员分享,可在线阅读,更多相关《processlab.docx(26页珍藏版)》请在冰豆网上搜索。

processlab.docx

processlab

实验四进程及进程管理

4.1使用ps命令查看进程信息

【实验内容】

ps是基本的Linux命令,通过本实验,不仅要熟悉ps命令方法,更重要的是可以了解Linux进程的组成。

【实验原理】

ps:

查看系统中的进程,Linux中可以使用ps-aux查看所有进程。

其中PID代表进程ID,TTY是该进程是由哪个控制台启动的,CMD则是命令。

如果想列出更详细的信息,则可使用命令:

“ps-auxw”。

参数w表示加宽显示的命令行,参数w可以写多次,通常最多写3次,表示加宽3次,这足以显示很长的命令行了。

【实验内容】

在shell提示符下输入如下命令,并解释输出的结果:

[root@vmroot]#ps

  PIDTTYTIMECMD

  16767pts/10:

00ps

  18029pts/10:

00bash

[root@vmroot]#psaux

PIDTTYTIMECMD

 …

4.2使用proc文件系统查看进程信息

【实验目的】

本实验将指导学员了解proc文件系统,通过proc文件系统查询进程信息,可以扩展到修改系统参数。

【实验原理】

/proc文件系统是一个虚拟文件系统,通过文件系统接口实现对内核的访问,输出系统运行状态。

它以文件系统的形式,为操作系统本身和应用进程之间的通信提供了一个界面,使应用程序能够安全,方便的获得系统当前的运行状况和内核的内部数据信息,并且可以修改某些系统的配置信息。

【实验内容】

1)认识proc文件系统的文件和目录

[root@vmroot]#cd/proc

[root@vmroot]#ls

2)通过proc文件系统查看系统当前进行状态

[root@vmroot]#cat/proc/self/status

3)查询文件句柄的当前使用情况

#cat/proc/sys/fs/file-nr

42615252458

file-nr文件显示了三个参数:

分配的文件句柄总数、当前使用的文件句柄数以及可以分配的最大文件句柄数。

如果需要增大/proc/sys/fs/file-max中的值,请确保正确设置ulimit。

对于2.4.20,通常将其设置为unlimited。

使用ulimit命令来验证ulimit设置:

[root@vmroot]#ulimit

unlimited

4)通过proc文件系统修改内核中预定的一些变量

1)修改整个系统中文件句柄的最大数量

[root@vmroot]#ls/proc/sys/fs/file-max

52458

[root@vmroot]#echo65536>/proc/sys/fs/file-max

[root@vmroot]#ls/proc/sys/fs/file-max

65536

2)修改网络TTL

[root@vmroot]#ls/proc/sys/net/ipv4/ip_default_ttl

64

[root@vmroot]#echo128>/proc/sys/net/ipv4/ip_default_ttl

[root@vmroot]#ls/proc/sys/net/ipv4/ip_default_ttl

128

3)修改系统中最大进程数量

[root@vmroot]#ls/proc/sys/kernel/pid_max

32768

[root@vmroot]#echo65536>/proc/sys/kernel/pid_max

[root@vmroot]#ls/proc/sys/kernel/pid_max

65536

4)修改普通用户的最大RTC频率

[root@vmroot]#ls/proc/sys/dev/rtc/max-user-freq

64

[root@vmroot]#echo128>/proc/sys/dev/rtc/max-user-freq

[root@vmroot]#ls/proc/sys/dev/rtc/max-user-freq

128

5)其他一些信息

[root@vmroot]#cat/proc/cpuinfo-CPU

[root@vmroot]#cat/proc/interrupts-中断

[root@vmroot]#cat/proc/ioports-设备IO端口

[root@vmroot]#cat/proc/meminfo-内存信息(i.e.memused,free,swapsize)

[root@vmroot]#cat/proc/partitions-所有设备的所有分区

[root@vmroot]#cat/proc/pci-PCI设备的信息

[root@vmroot]#cat/proc/swaps-所有Swap分区的信息

[root@vmroot]#cat/proc/version-Linux的版本号

4.3使用fork、exit和exec系统调用编写多进程程序

【实验目的】

本实验将通过编写fork等系统调用的程序,加深对系统进程及其控制的了解。

【实验原理】

fork后父子进程会同步运行,但父子进程的返回顺序是不确定的。

设两个变量global和test来检测父子进程共享资源的情况。

同时在进程退出时对exit和_exit的区别进行测试和说明。

【实验内容】

1.fork

#include

#include

#include

#include

#include

#include

//#include

intglobal=22;

charbuf[]="thetestcontent!

\n";

intmain(void)

{

inttest=0,stat;

pid_tpid;

if(write(STDOUT_FILENO,buf,sizeof(buf))!

=sizeof(buf))

{perror("writeerror!

");}

printf("forktest!

\n");

/*fork*/

pid=fork();/*weshouldchecktheerror*/

if(pid==-1)

{

perror("fork");

exit(0);

}

elseif(pid==0)

{

global++;test++;

printf("global=%dtest=%dChild,myPIDis%d\n",global,test,getpid());

exit(0);

}

/*elsebetheparent*/

global+=2;

test+=2;

printf("global=%dtest=%dParent,myPIDis%d\n",global,test,getpid());

exit(0);

//printf("global=%dtest=%dParent,myPIDis%d",global,test,getpid());

//_exit(0);

}

编译执行,并分析结果:

[root@localhostroot]#./test

thetestcontent!

forktest!

global=23test=1Child,myPIDis2751

global=24test=2Parent,myPIDis2750

可以看出父子进程打印出了各自的进程号和对应变量的值,显然global和test在父子进程间是独立的,其各自的操作不会对对方的值有影响。

将上述代码最后的两行代码替换为注释掉的_exit(0)行,重新编译,查看结果,解释原因:

[root@localhostroot]#./test

thetestcontent!

forktest!

global=23test=1Child,myPIDis2771

父进程的信息没有打印出来,其原因是:

_exit()函数直接使进程停止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;而exit()函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序。

exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,即会"清理I/O缓冲"。

若将上述_exit(0)改为exit(0),则肯定会有打印。

另外,需要注意换行符\n会引起IO的清理操作,若下面的语句printf("global=%dtest%dParent,myPIDis%d",global,test,getpid());加上\n,则调用_exit(0)的结果和调用exit(0)的结果是一样的。

2.vfork的特点

将上述代码的pid=fork();改为pid=vfork();编译后运行结果如下:

[root@localhostroot]#./test

thetestcontent!

forktest!

global=23test=1Child,myPIDis2849

global=25test=3Parent,myPIDis2848

可以看出,vfork与fork区别在于共享的资源不一样,vfork调用后,子进程先对global和test加1,父进程运行时,在其基础之上再加2,得到上述运行结果。

即vfork的特点是:

在调用execv或者exit前子进程对变量的修改会影响到父进程,即他们是共享的;

特别注意:

父进程等待子进程调用execv或exit才继续执行。

则若子进程依赖父进程的进一步动作时,父进程又必须阻塞到子进程调用execv或者exit才会往下执行,此时就会造成“死锁”。

读者可自己设计测试一下这种“死锁”状态。

4.4使用fork和exec系统调用编写执行命令的程序

【实验目的】

本实验将通过编写fork和exec等系统调用的程序,加深对系统进程及其控制的了解。

【实验原理】

fork后调用exec族函数来调用系统命令或者程序来实现系统shell功能。

【实验内容】

execv函数族的使用

注意点:

调用execv后,程序不再返回!

在上述代码基础上,在子进程的退出代码前加入如下代码:

printf("global=%dtest%dChild,myPIDis%d\n",global,test,getpid());

if(execl("/bin/ps","ps","-au",NULL)<0)

perror("execlerror!

");

printf("thismessagewillneverbeprinted!

\n");

exit(0);

编译运行后结果为:

[root@localhostroot]#./test

thetestcontent!

forktest!

global=23test=1Child,myPIDis2909

USERPID%CPU%MEMVSZRSSTTYSTATSTARTTIMECOMMAND

root27190.00.643601032pts/1S23:

140:

00/bin/bash

root29080.00.11340276pts/1R23:

380:

00./test

root29090.00.42684736pts/1R23:

380:

00ps-au

global=25test=3Parent,myPIDis2908

waitpid的作用是等待子进程退出并回收其资源,同时可以通过WIFEXITED等宏调用可以检测子进程退出的状态。

在第一个示例fork使用的代码基础上进行修改,添加检测进程退出状态的子函数,参考代码如下:

voidexit_check(intstat)

{

if(WIFEXITED(stat))

{printf("exitnormally!

thereturncodeis:

%d\n",WEXITSTATUS(stat));}

elseif(WIFSIGNALED(stat))

{printf("exitabnormally!

thesignalcodeis:

%d\n",WTERMSIG(stat));}

}

在父进程处理global和test变量前加入如下代码:

if(waitpid(pid,&stat,0)==pid)

{exit_check(stat);}//thestatusofexitcheck

编译运行后结果为:

[root@localhostroot]#./test

thetestcontent!

forktest!

global=23test=1Child,myPIDis2973

exitnormally!

thereturncodeis:

0

global=24test=2Parent,myPIDis2972

可以看出父进程回收了退出的子进程的资源,检测到了它的退出状态。

4.5编写一个守护进程

【实验目的】

守护进程是Linux系统开发中很重要的知识点,本实验要求学员编写一个守护进程,通过本实验,学员可以熟悉守护进程的编写过程。

【实验原理】

守护进程编写的主要步骤如下:

1)将程序进入后台执行。

由于守护进程最终脱离控制终端,到后台去运行。

方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。

这就是常说的“脱壳”。

子进程继续函数fork()的定义如下:

  pid_tfork(void);

2)脱离控制终端、登录会话和进程组。

开发人员如果要摆脱它们,不受它们的影响,一般使用setsid()设置新会话的领头进程,并与原来的登录会话和进程组脱离。

3)禁止进程重新打开控制终端。

4)重设文件权限掩码

5)关闭打开的文件描述符,并重定向标准输入、标准输出和标准错误输出的文件描述符。

进程从创建它的父进程那里继承了打开的文件描述符。

如果不关闭,将会浪费系统资源,引起无法预料的错误。

关闭三者的代码如下:

  for(fd=0,fdtablesize=getdtablesize();fd

  close(fd);

6)改变工作目录到根目录或特定目录进程活动时,其工作目录所在的文件系统不能卸下

【实验内容】

守护进程实例包括两部分:

主程序test.c和初始化程序init.c。

主程序每隔一分钟向/tmp目录中的日志test.log报告运行状态。

初始化程序中的init_daemon函数负责生成守护进程。

读者可以利用init_daemon函数生成自己的守护进程。

1.init.c

#include

#include

#include

#include

voidinit_daemon(void)

{

intpid;

inti;

if(pid=fork()){exit(0);}//是父进程,结束父进程

elseif(pid<0){exit(-1);}//fork失败,退出

setsid();//第一子进程成为新的会话组长和进程组长

//并与控制终端分离

if(pid=fork()){exit(0);}//是第一子进程,结束第一子进程

elseif(pid<0){exit

(1);}//fork失败,退出

//第二子进程不再是会话组长

for(i=0;i

close(i);

chdir("/tmp");//改变工作目录到/tmp

umask(0);

//重设文件创建掩模

return;

}

2.test.c

#include

#include

voidinit_daemon(void);//守护进程初始化函数

intmain()

{

FILE*fp;

time_tt;

init_daemon();//初始化为Daemon

while

(1)//每隔2秒钟向test.log报告运行状态

{

sleep

(2);//睡眠2秒钟

if((fp=fopen("test.log","a"))!

=NULL)

{

t=time(0);

fprintf(fp,"I'mhereat%sn",asctime(localtime(&t)));

fclose(fp);

}

}

return0;

}

编译:

[root@vmroot]#gcc–g–otestinit.ctest.c

执行:

[root@vmroot]#./test

查看进程:

[root@vmroot]#ps–ef

从输出可以发现test守护进程的各种特性满足上面的要求。

实验五进程间通信

UNIX/LINUX系统的进程间通信机构(IPC)允许在进程间交换数据。

本实验的目的是了解和熟悉LINUX支持的管道机制、信号机制、消息队列通信机制及共享存储区机制。

5.1无名管道通信实验

【实验目的】

1、了解什么是管道

2、熟悉UNIX/LINUX支持的管道通信方式

 【实验内容】

编写程序实现进程的管道通信。

用系统调用pipe()建立一管道,二个子进程P1和P2分别向管道各写一句话:

   Child1issendingamessage!

   Child2issendingamessage!

父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。

参考程序

#include

#include

intpid1,pid2;

 

main()

{

intfd[2];

charoutpipe[100],inpipe[100];

pipe(fd);                      /*创建一个管道*/

while((pid1=fork())==-1);

if(pid1==0)

{

lockf(fd[1],1,0);

   sprintf(outpipe,"child1processissendingmessage!

");

/*把串放入数组outpipe中*/

   write(fd[1],outpipe,50);    /*向管道写长为50字节的串*/

   sleep(5);                /*自我阻塞5秒*/

   lockf(fd[1],0,0);

   exit(0);

 }

else

 {

while((pid2=fork())==-1);

   if(pid2==0)

{   lockf(fd[1],1,0);          /*互斥*/

  sprintf(outpipe,"child2processissendingmessage!

");

         write(fd[1],outpipe,50);

         sleep(5);

          lockf(fd[1],0,0);

          exit(0);

        }

       else

       { wait(NULL);             /*同步*/

        read(fd[0],inpipe,50);  /*从管道中读长为50字节的串*/

            printf("%s/n",inpipe);

        wait(NULL);

        read(fd[0],inpipe,50);

        printf("%s/n",inpipe);

             exit(0);

         }

   }

}

运行结果,延迟5秒后显示

child1processissendingmessage!

 再延迟5秒

child2processissendingmessage!

5.2有名管道通信实验

【实验目的】

1、掌握有名管道的创建和读写方式

2、熟悉UNIX/LINUX支持的有名管道通信方式

 【实验内容】

1.创建有名管道

2.本进程执行循环等待数据被写入到管道中并读有名管道

3.打开有名管道并写数据到名管道

参考代码:

//read_fifo.c

#include

#include

#include

#include

#include

#include

#include

#defineBUFFER_SIZE1024

intmain(intargc,char**argv)

{

intfd;

if(argc<2)

{

fprintf(stdout,"Usage:

%s\n",argv[0]);

exit

(1);

}

//intopen(constchar*path,intoflag,...);

if((fd=open(argv[1],O_RDONLY))<0)

{

fprintf(stderr,"openfifo%sforreadingfailed:

%s\n",argv[1],strerror(errno));

exit

(1);

}

fprintf(stdout,"openfifo%sforreadingsuccessed.\n",argv[0]);

charbuffer[BUFFER_SIZE];

ssize_tn;

while

(1)

{

again:

//ssize_tread(intfd,void*buf,size_tcount);

if((n=read(fd,buffer,BUFFER_SIZE))<0)

{

if(errno==EINTR)

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 交通运输

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1