Linux程序设计实验

Linux程序设计实验
Linux程序设计实验

Linux程序设计实验7

——进程通信1

一、实验目的

1.掌握常用的几种中断方法;

2.掌握signal函数实现信号处理程序设计院;

3.掌握多信号时的信号处理程序编写;

4.掌握应用管道实现信号处理的方法。

二、实验任务与要求

1.alarm函数产生的SIGALRM信号;

2.应用signal函数实现信号处理程序编写;

3.多信号时的信号处理程序编写;

4.应用管道实现信号处理的编写;

三、实验工具与准备

计算机PC机,Linux Redhat Fedora Core6操作系统

四、实验步骤与操作指导

任务1:硬中断实例

运行下列程序kk1.c:

#include

int main(void)

{

while(1);

return 0;

}

(1)程序运行过程中,请你使用硬中断Ctrl+C或Ctrl-\中断程序的执行。

(2)可以使用信号SIGSEGV中断此程序,方法是先在后台运行此程序,得出程序进程号,然后用命令kill发送信号SIGSEGV,如下形式:

[root@localhost root]# ./kk &

[root@localhost root]# [1] 7940

[root@localhost root]# kill -SIGSEGV 7940

根据提示,运行程序,结果如下:

任务2:使用软件中断。alarm函数和SIGALRM信号,调用alarm函数设定一个闹钟,告诉内核在seconds秒之后给当前进程发SIGALRM信号,该信号的默认处理动作是终止当前进程。这个函数的返回值是0或者是以前设定的闹钟时间还余下的秒数。

程序源代码kk2.c:

#include

#include

int main(void)

{

int counter;

alarm(10);

for(counter=0; 1; counter++)

printf("counter=%d ", counter);

return 0;

}

程序的作用是10秒钟之内不停地数数,10秒钟到了就被SIGALRM信号中断。

程序运行结果:

任务3:程序设计。设计一个程序,要求程序运行后进入无限循环,在无限循环中每3秒输出一条语句;当用户按下中断组合键(Ctrl+C)发送信号SIGINT,此时调用信号处理函数(自定义函数fun_ctrl_c)。在程序正常结束前,再应用signal函数(用参数SIG_DFL),恢复系统对信号的默认处理方式。

提示:源代码可参考教材P211,例证-4

(1)修改程序,要求程序运行后进入一个无限循环,当用户按下中断键(Ctrl+Z)时,进入程序的自定义信号处理函数,当用户再次按下中断键(Ctrl+Z)后,结束程序运行。源程序代码:

程序运行结果:

(2)修改程序,要求程序运行后进入一个无限循环,当用户按下中断键(Ctrl+Z)时,进入程序的自定义信号处理函数,当用户再次按下中断键(Ctrl+Z)后,程序仍能继续运行。

源程序代码:

程序运行结果:

任务4 调试下列程序。程序中能处理三种不同的信号,其中信号SIGINT(Ctrl+C键)和SIGTSTP(Ctrl+Z键)是可阻塞的,而信号SIGQUIT(Ctrl+\ 键)是不可阻塞的,程序源代码如下:

#include

#include

#include

#include

#include

void fun_ctrl_c();

void fun_ctrl_z();

void fun_ctrl_d();

int main()

{ /*C程序的主函数,开始入口 */

int i;

sigset_t set, pendset;

struct sigaction action;

(void) signal(SIGINT, fun_ctrl_c); /*调用fun_ctrl_c函数 */

(void) signal(SIGTSTP,fun_ctrl_z);

(void) signal(SIGQUIT, fun_ctrl_d);

if (sigemptyset(&set) < 0) /*初始化信号集合 */

perror("初始化信号集合错误");

if (sigaddset(&set, SIGINT) < 0) /*把SIGINT信号加入信号集合 */

perror("Ctrl+C加入信号集合错误");

if (sigaddset(&set, SIGTSTP) < 0)

perror("Ctrl+Z加入信号集合错误");

if (sigprocmask(SIG_BLOCK, &set, NULL) < 0)

perror("往信号阻塞集增加一个信号集合错误");

else

{

for (i = 0; i < 10; i++) {

printf("Ctrl+C、Ctrl+Z信号处理处于阻塞状态,能及时处理'Ctrl+\'信号\n "); sleep(3);

}

}

if (sigprocmask(SIG_UNBLOCK, &set, NULL) < 0)

/*当前的阻塞集中删除一个信号集合 */

perror("从信号阻塞集删除一个信号集合错误");

}

void fun_ctrl_c() /*自定义信号处理函数 */

{

int n ;

printf("\t你按了Ctrl+C 系统是不是很长时间没理你?\n");

for(n=0;n<4;n++)

printf("\t正在处理Ctrl+C信号处理函数 \n");

}

void fun_ctrl_z() /*自定义信号处理函数 */

{

int n ;

printf("\t你按了Ctrl+Z 系统是不是很长时间没理你?\n");

for(n=0;n<6;n++)

printf("\t正在处理Ctrl+Z信号处理函数 \n");

}

void fun_ctrl_d( ) /*自定义信号处理函数 */

{

int n;

printf("\t你按了'Ctrl+\' 系统及时地处理了此信号处理函数\n");

for(n=0;n<2;n++)

printf("\t正在处理Ctrl+/ 信号处理函数 \n");

}

问题:调试此程序,说明此程序的中断机制;

说明此程序的中断机制:

程序运行结果:

任务5:程序设计。设计一个程序要求创建一个管道,复制进程,父进程往管道中写入字符串,子进程从管道中读取前输出字符串。

提示:主程序调用pipe函数创建一个管道,调用fork函数创建进程;父进程中先用close(pipe_fd[0])关闭pipe_fd[0],剩下的pipe_fd[1]用来把数据写入管道,利用write函数写入字符串,然后用close(pipe_fd[1])关闭pipe_fd[1];子进程是用close(pipe_fd[1])关闭pipe_fd[1],剩下的pipe_fd[0]用来从管道读取数据,利用read函数读取字符串,然后用close(pipe_fd[0])关闭pipe_fd[0]。

#include

#include

#include

#include

#include

#include

int main ()

pid_t result;

int r_num;

int pipe_fd[2];

char buf_r[100],buf_w[100];

memset(buf_r,0,sizeof(buf_r));

if(pipe(pipe_fd)<0)

{

printf("创建管道失败");

return -1;

}

result=fork();

if(result<0)

{

perror("创建子进程失败");

exit(0) ;

}

else if (result==0) /*子进程运行代码段*/

{

close(pipe_fd[1]);

if((r_num=read(pipe_fd[0],buf_r,100))>0)

printf("子进程从管道读取%d个字符,读取的字符串是:%s\n",r_num,buf_r); close(pipe_fd[0]);

exit(0);

}

else /*父进程运行代码段*/

{

close(pipe_fd[0]);

printf("请从键盘输入写入管道的字符串\n");

scanf("%s",buf_w);

if(write(pipe_fd[1],buf_w,strlen(buf_w))!=-1)

printf("父进程向管道写入:%s\n",buf_w);

close(pipe_fd[1]);

waitpid(result,NULL,0);//调用waitpid, 阻塞父进程,等待子进程退出 exit(0);

}

问题:修改以上程序,要求父进程读取文件kk1.c内容(即任务1的源代码),把读出的字符串写入管道,子进程从管道中读取前输出字符串。

修改后的源程序代码:

程序运行结果:

相关主题
相关文档
最新文档