Linux程序设计实验
![Linux程序设计实验](https://img.360docs.net/img5b/1appzrw2zaw5nstjy5ie3bbc9kusptiw-b1.webp)
![Linux程序设计实验](https://img.360docs.net/img5b/1appzrw2zaw5nstjy5ie3bbc9kusptiw-b2.webp)
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的源代码),把读出的字符串写入管道,子进程从管道中读取前输出字符串。
修改后的源程序代码:
程序运行结果: