文章目录
题目
1.请编写一个程序,设置SIGINT和SIGQUIT信号,并在该程序中实现从文件中读取信息的操作,
并保证在读取文件且只有在读取文件的过程中不会被发送的SIGINT和SIGQUIT信号所打断。
//请编写一个程序,设置SIGINT和SIGQUIT信号,并在该程序中实现从文件中读取信息的操作,并保证在读取文件且只有在读取文件的过程中不会被发送的SIGINT和SIGQUIT信号所打断。
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void sighandler(int signo)
{
if((signo == SIGINT) || (signo == SIGQUIT))
{
printf("解除阻止\n");
}
}
int main(int argc,char* args[])
{
int flag; //标识文件读取状态
sigset_t best; //阻塞信号
sigemptyset(&best); //清空信号集
sigaddset(&best,SIGINT); //添加阻塞信号
sigaddset(&best,SIGQUIT);
sigprocmask(SIG_BLOCK,&best,NULL); //将SIG_BLOCK和best信号或操作
if(signal(SIGINT,sighandler) == SIG_ERR)
{
perror("signal error");
return -1;
}
if(signal(SIGQUIT,sighandler) == SIGQUIT)
{
perror("signal error");
return -1;
}
FILE *fp = NULL;
fp = fopen("./a.txt","r");
if(fp == NULL)
{
printf("文件打开失败\n");
return -1;
}
printf("请输入是否开始读取文件 1代表读,0代表不读\n");
scanf("%d",&flag);
while(1)
{
if(flag == 1)
{
break;
}
else if(flag == 0)
{
pause();
}
}
char buffer[1024];
while(1)
{
memset(buffer,0,sizeof(buffer));
char *temp = fgets(buffer,sizeof(buffer),fp);
if(temp == NULL)
{
break;
}
printf("buffer = %s\n",buffer);
}
if(fp != NULL)
{
fclose(fp);
}
printf("read ends\n");
sigset_t uset;
sigemptyset(&uset);
sigaddset(&uset,SIGINT);
sigaddset(&uset,SIGQUIT);
sigprocmask(SIG_BLOCK,&uset,NULL);
while(1)
{
pause();
}
return 0;
}
2.编程一个基本多进程测试框架,提示用户输入进程数、和每个进程数运行圈数。进行多进程压力测试。
要求父进程能监控所有子进程的退出,避免僵尸进程。
//2、编程一个基本多进程测试框架,提示用户输入进程数、和每个进程数运行圈数。进行多进程压力测试。要求父进程能监控所有子进程的退出,避免僵尸进程。
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void TestFunc(int num)
{
printf("%d\n",num++);
}
int main()
{
pid_t pid;
int process_num;
int process_run;
int i, j;
printf("线程数:");
scanf("%d",&process_num);
printf("圈数:");
scanf("%d",&process_run);
for(i = 0; i < process_num; i++)
{
pid = fork();
if(pid == 0)
{
for(j = 0; j < process_run; j++)
{
TestFunc(j);
}
exit(0);
}
}
while(1)
{
wait(NULL);
}
printf("main ends\n");
return 0;
}
3.信号可靠信号不可靠信号相关
编程程序,要去实现如下功能:
父进程创建子进程1和子进程2、子进程1向子进程2发送可靠信号,并传送额外数据为子进程1的pid*2;
子进程2接受可靠信号的值,并发送给父进程,父进程把接受的值进行打印。
提示:用sigqueue和sigaction实现
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
/*
1因为孩子1的pid和孩子2的pid全部在父进程中
2 父进程把孩子2的pid,发给孩子1
3、孩子1有了孩子2的pid,孩子1就可以给孩子2发送信号了。
*/
int pidArray[10]; //写时拷贝copy-on-write 如果全区变量值改变,子进程另外拷贝
void myhandle(int num,siginfo_t *st, void *p)
{
int val = 0;
//printf("recve num:%d,data=%d\n",num,st->si_value.sival_int);
if (num == SIGRTMIN+1)
{
//孩子1接收到了信号
printf("孩子1收到信号,值:%d \n", st->si_value.sival_int);//父进程将子进程2的pid这个数据发给了,子进程1
pidArray[1] = st->si_value.sival_int;// 子进程1将从父进程收到的数据放在本全局区pidArray[1]中
}
if (num == SIGRTMIN+2)
{
//孩子2接收到了信号
printf("孩子2收到信号,值:%d \n", st->si_value.sival_int);//子进程1将自己的2*pid值发给子进程2
pidArray[3] = st->si_value.sival_int;//子进程2将子进程1发送的数据存到本全局区中
}
if (num == SIGRTMIN+3)
{
//父进程接收到了信号
printf("父进程收到信号,值:%d \n", st->si_value.sival_int);//子进程2将自己收到的数据又发给父进程
printf("父进程中的pid[0]:%d pid[1]:%d \n", pidArray[0], pidArray[1]);//输出自己全局区中原来存的数据
pidArray[3] = st->si_value.sival_int;//父进程将从子进程2收到的数据存入本全局区中
}
}
int main()
{
int i = 0;
struct sigaction act;
act.sa_sigaction=myhandle;
act.sa_flags=SA_SIGINFO;
//注册信号 处理函数
if(sigaction(SIGRTMIN+1,&act,NULL)==-1)
{
perror("func sigaction err:");
return -2;
}
//注册信号 处理函数
if(sigaction(SIGRTMIN+2,&act,NULL)==-1)
{
perror("func sigaction err:");
return -2;
}
//注册信号 处理函数
if(sigaction(SIGRTMIN+3,&act,NULL)==-1)
{
perror("func sigaction err:");
return -2;
}
int pid = 0;
for (i=0; i<2; i++)
{
//父进程可以把所有的孩子ID缓存下来
pidArray[i] = pid = fork();
if (pid == 0)
{
break; //如果是孩子,不参与fork
}
else if (pid > 0)
{
;
}
}
if (pid > 0)
{
printf("父进程运行\n");
//父进程给进程1发送信号 把进程2的pid发过去
//添加额外数据
union sigval mysigval;
mysigval.sival_int=pidArray[1];
//发送消息
int res;
res = sigqueue(pidArray[0],SIGRTMIN+1, mysigval);
}
//子进程1
if (pid==0 && i==0)
{
printf("子进程1运行\n");
printf("子进程sleep\n");
sleep(5);
printf("子进程sleep被打断以后,全局变量有值了\n");
//添加额外数据
union sigval mysigval;
mysigval.sival_int=getpid()*2;
//发送消息
int res;
printf("子进程1给进程2发送信号getpid()*2:%d \n", getpid()*2);
res = sigqueue(pidArray[1],SIGRTMIN+2, mysigval);
exit(0);
}
//子进程2
if (pid==0 && i==1)
{
sleep(10);
printf("子进程2睡眠醒来,开始发信号\n");
//添加额外数据
union sigval mysigval;
mysigval.sival_int=pidArray[3];
//发送消息
int res;
printf("子进程2给父进程发送信号pidArray[3]%d \n", pidArray[3]);
res = sigqueue(getppid(),SIGRTMIN+3, mysigval);
exit(0);
}
sleep(2);
int mypid = 0;
while ( (mypid = waitpid(-1, NULL, WNOHANG)) > 0)
{
printf("子进程退出pid:%d \n", mypid);
}
return 0;
}
4.设计一个Shell程序,在/$HONE/test目录下建立50个目录,即user1~user50,
并设置每个目录的权限,其中其他用户的权限为:读;文件所有者的权限为:
读、写、执行;文件所有者所在组的权限为:读、执行。
#!/bin/sh
i=0
while [$i -lt 50 ]
do
i=`expr $i + 1`
mkdir -p ./home/user$i
chmod 754 ./home/user$i
done
5.shell程序
编写shell程序,添加一个新组为class1,然后添加属于这个组的20个用户,
用户名的形式为stdxx,其中xx从01到20。
#!/bin/sh
i=1
while [ $i -le 2 ]
do
if [$i -le 9]
then
USERNAME=systemk1t${i}
fi
useradd $USERNAME
mkdir /home/$USERNAME
chown -R $USERNAME /home/$USERNAME
chgrp -R class1 /home/$USERNAME
i=$(($i + 1))
done