processlabWord文档格式.docx

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

processlabWord文档格式.docx

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

processlabWord文档格式.docx

对于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

65536

2)修改网络TTL

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

64

[root@vmroot]#echo128>

/proc/sys/net/ipv4/ip_default_ttl

128

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

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

32768

/proc/sys/kernel/pid_max

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

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

/proc/sys/dev/rtc/max-user-freq

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<

stdio.h>

sys/types.h>

sys/wait.h>

unistd.h>

stdlib.h>

fcntl.h>

//#include<

sys/exits.h>

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!

/*fork*/

pid=fork();

/*weshouldchecktheerror*/

if(pid==-1)

{

perror("

fork"

exit(0);

}

elseif(pid==0)

global++;

test++;

global=%dtest=%dChild,myPIDis%d\n"

global,test,getpid());

exit(0);

/*elsebetheparent*/

global+=2;

test+=2;

printf("

global=%dtest=%dParent,myPIDis%d\n"

//printf("

global=%dtest=%dParent,myPIDis%d"

//_exit(0);

编译执行,并分析结果:

[root@localhostroot]#./test

global=23test=1Child,myPIDis2751

global=24test=2Parent,myPIDis2750

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

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

[root@localhostroot]#./test

global=23test=1Child,myPIDis2771

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

_exit()函数直接使进程停止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;

而exit()函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序。

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

清理I/O缓冲"

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

另外,需要注意换行符\n会引起IO的清理操作,若下面的语句printf("

global=%dtest%dParent,myPIDis%d"

加上\n,则调用_exit(0)的结果和调用exit(0)的结果是一样的。

2.vfork的特点

将上述代码的pid=fork();

改为pid=vfork();

编译后运行结果如下:

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后,程序不再返回!

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

global=%dtest%dChild,myPIDis%d\n"

if(execl("

/bin/ps"

"

ps"

-au"

NULL)<

0)

execlerror!

thismessagewillneverbeprinted!

exit(0);

编译运行后结果为:

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:

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:

WTERMSIG(stat));

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

if(waitpid(pid,&

stat,0)==pid)

{exit_check(stat);

}//thestatusofexitcheck

global=23test=1Child,myPIDis2973

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<

fdtablesize;

fd++)

  close(fd);

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

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

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

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

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

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

1.init.c

unistd.h>

sys/types.h>

sys/stat.h>

voidinit_daemon(void)

intpid;

inti;

if(pid=fork()){exit(0);

}//是父进程,结束父进程

elseif(pid<

0){exit(-1);

}//fork失败,退出

setsid();

//第一子进程成为新的会话组长和进程组长

//并与控制终端分离

}//是第一子进程,结束第一子进程

0){exit

(1);

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

for(i=0;

i<

getdtablesize();

++i)//关闭打开的文件描述符

close(i);

chdir("

/tmp"

//改变工作目录到/tmp

umask(0);

//重设文件创建掩模

return;

}

2.test.c

stdio.h>

time.h>

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)。

参考程序

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);

else

{

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

if(pid2==0)

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

/*互斥*/

child2processissendingmessage!

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

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

 

else

wait(NULL);

/*同步*/

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

/*从管道中读长为50字节的串*/

%s/n"

inpipe);

wait(NULL);

printf("

inpipe);

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

再延迟5秒

5.2有名管道通信实验

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

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

1.创建有名管道

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

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

参考代码:

//read_fifo.c

sys/stat.h>

string.h>

errno.h>

#defineBUFFER_SIZE1024

intmain(intargc,char**argv)

intfd;

if(argc<

2)

fprintf(stdout,"

Usage:

%s<

filename>

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));

openfifo%sforreadingsuccessed.\n"

charbuffer[BUFFER_SIZE];

ssize_tn;

while

(1)

again:

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

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

if(errno==EINTR)

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

当前位置:首页 > 高等教育 > 工学

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

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