Linux编程技术:期末复习

考前复习

1. 分区与目录对应,叫做:挂载

2. 信号在软件层上叫:中断机制,是一种异步中断

3. gcc编译过程:预处理、编译、汇编、连接

4. 编译有线程的文件加:-lpthread

5. 父进程等待子进程用:wait()、waitpid()

6. Linux主要的信号安装函数有:signal()、sigaction()

7. Linux由C和汇编编写完成

8. Linux启动用到的程序在:/boot目录下

9. 一对一线程机制,就是一个用户线程对应一个:内核线程

10. vim中,在命令模式下按:“ : ”  进入底行模式

11. Linux文件系统由:引导块、超级块、数据块、索引节点,这四部分组成,超级块存放文件的控制信息

12. 线程本身调用pthread_exit()函数可以退出线程

13. 向消息队列发送信息的函数是:msgrcv()

14. stat()系统调用可以根据文件描述符来操作文件的特性

15. Memcheck是一个内存检查器,Cachegrind是检查程序中缓存使用出现的问题

16. setitimer()用于设置定时器,当计时时间到时,向进程发送SIGALRM信号

17. 当进程的属性设置为:分离状态,该线程结束时立刻释放它所占有的系统资源

18. 接到一个信号并终止,属于异常终止一个进程

19. 创建线程私有数据命令:pthread_create()

20. 适用于进程之间的通信的通信方式:套接字

21. 创建和打开消息队列的函数为:msgget()

22. 通过调用pid_t waitpid(pit_t pid, int *statloc, int options)得到进程的退出信息,当第一个参数pid取为-1时,表示等待任意子进程退出,相当于wait()

23. int kill(pid_t pid , int signo);当第一个参数pid>0时,表示发送信号给进程id为pid的进程

24. shmat()将共享主存区映射到进程虚拟地址空间

25. 修改消息队列状态信息的命令是msgctl()

26. gdb调试程序时,next: 单步运行,不进入函数内部;step:单步运行,进入函数内部

27. Linux系统的设备文件分为:字符设备文件、块设备文件、网络设备文件

28. I/O提供了三种类型的缓存:全缓冲、行缓冲、不带缓冲

29. 信号的生命周期:信号诞生、信号在进程中注册、信号处理函数执行完毕、信号在进程中注销

30. 互斥锁的两中状态:开锁、上锁

31. 在I/O库中,rewind()将文件流指针指向文件的起始位置

32. 没有明确给定的全局变量和静态变量存放在:未初始化数据区

33. geteuid()用于得到进程的:用户有效UID

34. 一个进程是PCB结构与数据的组合

35. 父进程调用wait() 可能出现的三种情况?

    1. 当有子进程退出时wait返回子进程的pid并且获取到子进程的退出状态

    2. 当没有子进程退出时 父进程将阻塞等待子进程退出

    3. 当没有子进程时,wait返回-1

36. 返回调用进程的进程标识号的系统函数是:getpid()

37. 什么是线程?进程和线程的区别?

    1. 线程是操作系统进程中能够并发执行的实体,是处理器调度和分派的基本单位。

    2. 区别 :

       1. 调度

          在传统操作系统中进程是拥有资源和调度的基本单位

          在引入了线程的操作系统中 线程是操作系统分派和调度的基本单位	

          进程是拥有资源的基本单位

       2. 并发性

          进程之间可以并发执行,在同一进程中的线程也可以并发执行 

       3. 拥有资源 

          进程是拥有系统资源的基本单位 

          线程基本上不拥有系统资源,但也拥有其运行所必要的资源,在同一进程中的线程共享进程的地址空间

       4. 系统开销

          创建或撤销进程时,系统都要为其创建和回收进程控制块(PCB) 

          进程的创建和撤销的开销远大于线程的开销

          在进程切换时,涉及到当前进程CPU环境的保存以及新被调度运行进程的CPU环境的设置,而线程的切换则仅需保存和设置少量寄存器内容 

          进程切换的开销也是远大于线程的

38. pid_t fork() 返回值的意义?

    若执行成功,父进程中将返回子进程(新创建的进程)的PID,类型为pid_t,子进程将返回0,以区别父子进程;

    若执行失败,则在父进程中返回-1,错误原因存储在errno中

39. 在进程中,return和exit() 的区别?

    如果是在main函数中exit和return都是终止进程 但是return会弹栈 exit不会;

    如果是在函数中return 返回到上级函数调用的位置,exit会终止进程

40. 什么是孤儿进程?谁负责回收孤儿进程的内核空间资源?

    父进程先于子进程结束 则子进程称为孤儿进程 由init 0接管并回收其内核资源

41. 什么是僵尸进程?如何消灭僵尸进程?

    僵尸进程 :子进程结束但是父进程未回收其内核资源,可以通过调用wait()或waitpid() 或者使其成为孤儿进程 由操作系统回收其内核资源

42. 进程对可靠信号和不可靠信号的处理过程。

    不可靠信号:不支持排队 如果在进程屏蔽信号时 给其发送多个不可靠信号,在取消屏蔽后只会接收到一个 

    可靠信号:支持排队  如果在进程屏蔽信号时 发送多个信号,在取消屏蔽后会按照先后顺序接收到所有可靠信号

43. 信号的定义及其分类。

    信号是一种软中断,用来通知进程发生了异步事件,  0~31分为不可靠信号, 32~63为可靠信号

44. 匿名管道及其特点。

    匿名管道:用于实现有亲缘关系的进程之间相互通信 ,创建在内核空间,通信结束后消失

45. 有名管道和匿名管道的区别?

    无名管道用于实现具有亲缘关系的进程间通信 ;有名管道用于实现非亲缘关系的进程间通信;

    有名管道 是一个特殊的文件 结束通信后内容消失但文件不消失;无名管道 结束通信后消失

46. 进程和线程的区别?

    线程是操作系统进程中能够并发执行的实体,是处理器调度和分派的基本单位。

    区别 :

    1.调度

    在传统操作系统中进程是拥有资源和调度的基本单位

    在引入了线程的操作系统中 线程是操作系统分派和调度的基本单位	

    进程是拥有资源的基本单位

    2.并发性

     进程之间可以并发执行,在同一进程中的线程也可以并发执行 

    3.拥有资源 

    进程是拥有系统资源的基本单位 

    线程基本上不拥有系统资源,但也拥有其运行所必要的资源,在同一进程中的线程共享进程的地址空间

    4.系统开销

    创建或撤销进程时,系统都要为其创建和回收进程控制块(PCB) 

    进程的创建和撤销的开销远大于线程的开销

    在进程切换时,涉及到当前进程CPU环境的保存以及新被调度运行进程的CPU环境的设置,而线程的切换则仅需保存和设置少量寄存器内容 

    进程切换的开销也是远大于线程的

47. Please describe the difference of signal() and sigaction() in brief

    不同点

    signal()

    安装的信号不能向信号处理函数传递信息

    sigaction()

    可设置进程的信号掩码,返回设置之前的sigaction结构

    安装的信号可以向信号处理函数传递信息

    相同点

    都可以为指定的信号设置信号处理函数

    共用同一个内核函数do_sigaction()

编程:
实验一
1.创建文件file1,写入字符串“abcdefghijklmn”;
2.创建文件file2,写入字符串“ABCDEFGHIJKLMN”;
3.读取file1中的内容,写入file2,使file2中的字符串内容为“abcdefghijklmn ABCDEFGHIJKLMN”
创建file1,file2 文件*

IO_open.c

#include<stdio.h>
    #include<fcntl.h>
    #include<unistd.h>
    #include<string.h>
    int main(int argc,char *argv[])
    {
        int IO_OPEN,IO_OPEN_1;//文件描述符 
        int write_num1,write_num2=-1;
        char *buf="abcdefghijklmn";
        char *buf2="ABCDEFGHIJKLMN";
        if(argc<3)
        {
            printf("ERROR!number<3\n") ;
            return -1;
        }
        IO_OPEN=open(argv[1],O_CREAT|O_RDWR,0755);
        if(IO_OPEN==-1)
        {
            perror("open");
            return -1;
        }
        IO_OPEN_1=open(argv[2],O_CREAT|O_RDWR,0755);
        if(IO_OPEN_1==-1)
        {
            perror("open");
            return -1;
        }
        write_num1=write(IO_OPEN,buf,strlen(buf));
        write_num2=write(IO_OPEN_1,buf2,strlen(buf2));
        close(IO_OPEN); 
        close(IO_OPEN_1);
        return 0;
    }         

实现file1中的字符串写入file2中
IO_file_rw.c

 #include<stdio.h>
 #include<fcntl.h>
 #include<unistd.h>
 int main(int argc,char *argv[])
 {
     int fd,fd2=-1;
     int rd_num,rd_num2,wt_num=-1;
     char buf[128]={0};
     char buf1[128]={0};
     if(argc<3)
     {
         printf("ERROR!\n");
         return -1;
     }
     if((fd=open(argv[1],O_RDONLY))==-1)//以读写方式打开file1
     {
         perror("open");
         return -1;
     }
     if((fd2=open(argv[2],O_RDWR))==-1)//打开file2
     {
         perror("open");
         return -1;
     }
     rd_num=read(fd,buf,128);
     rd_num2=read(fd2,buf1,128);
     /* 先将file2 文件中的字符串向后移动rd_num(file中的字符串长度)个位置*/
     lseek(fd2,rd_num,SEEK_SET);
     write(fd2,buf1,rd_num2);
     lseek(fd2,0,SEEK_SET);
     write(fd2,buf,rd_num);
 /*  lseek(fd2,0,SEEK_SET);   //先将file1中的字符串写入file2 再将file2中的字符串追加到后面
     write(fd2,buf,rd_num);
 write(fd2,buf1,rd_num2);*/
 close(fd2);
 close(fd);
     return 0;
 }

实验二
编写代码,完成以下功能:
1.创建新文件,该文件具有用户读写权限
2.采用dup/dup2/fcntl复制一个新的文件描述符,通过新文件描述符向文件写入“class_name”字符串;
3.通过原有的文件描述符读取文件中的内容,并且打印显示;

    #include<stdio.h>
    #include<fcntl.h>
    #include<unistd.h>
    #include<string.h>
    #include<sys/stat.h>
    int main(int argc,char *argv[])
    {
        int fd=-1;
        int fd2=-1;//新的文件描述符
        int wrnum,rdnum=0;
        char *buf="hello world\n";
        char buf1[128]={0};
        umask(0);//修改umask值
        fd=open(argv[1],O_CREAT|O_RDWR,0600);
        if(fd==-1)
        {
            perror("open");
            return -1;
        }
        //复制文件描述符
        fd2=dup(fd);//选取未被使用的最小的文件描述法
    //  fd2=dup2(fd,5);//使用指定的文件描述符 如果该文件描述符已被使用则关闭该文件描述符 重新使用
    //  fd2=fcntl(fd,F_DUPFD,1);//实现文件描述符复制,选择大于等于1的未被使用的文件描述符
        wrnum=write(fd2,buf,strlen(buf));//使用新的文件描述符写入字符串
        if(wrnum==0)//如果写入失败
        {
            perror("write");
            return -1;  
        }
        //此时文件指针位于文件末尾
        lseek(fd,0,SEEK_SET);//将文件指针指向文件开始
        rdnum=read(fd,buf1,128);//使用老的文件描述符将文件中的信息读取到buf1中
        if(rdnum==0)
        {
            perror("read");
            return -1;
        }
    printf("%s",buf1);//打印出读取的字符串
    close(fd);
    close(fd2);
        return 0;
    }               

编写程序完成以下功能:
1. 递归遍历home目录,打印出所有文件和子目录名称及节点号。
2. 判断文件类型,如果是子目录,继续进行递归遍历,直到遍历完所有子目录为止。

IO_dirread.c源码

    #include<stdio.h>
    #include<fcntl.h>
    #include<unistd.h>
    #include<dirent.h>
    #include<sys/stat.h>
    #include<string.h>
    int main(int argc,char *argv[])
    {
    	int dir_read(const char *str);
    	dir_read(argv[1]);
    	return 0;
    }
    int dir_read(const char * str)
    {
    	struct stat buf;
    	struct dirent *dirp=NULL;
    	DIR *dir=NULL;
    	char BUF[512]={0};
    	if((dir=opendir(str))==NULL)
        {     
            perror("opendir");
            return -1;
        }   
    	while((dirp=readdir(dir))!=NULL)
    	{
    		sprintf(BUF,"%s%s%s",str,"/",dirp->d_name);//获取目录的绝对路径			
    		if(dirp->d_name[0]=='.')//跳过隐藏文件
    			 continue;
    		if(stat(BUF,&buf)==-1)//需要使用绝对路径
    		{
    			perror("stat");
    			return -1;
    		}
    		if(S_ISDIR(buf.st_mode))//如果当前文件为目录,则递归查看其子目录
    		{
    			printf("%s %ld\n",BUF,dirp->d_ino);
    			dir_read(BUF);
    		}
    		else
    		{
    			printf("%s %ld \n",dirp->d_name,dirp->d_ino);
    		}
    	}
    	closedir(dir);
    }

实验三
创建子进程
1.在子进程中打开文件file1,写入自己的“班级_姓名_学号”
2.父进程读取file1中的内容,并且打印显示。
3.在父进程中获取已经结束的子进程的状态信息,打印该信息,并且打印结束的子进程的进程号。

   #include<stdio.h>
   #include<fcntl.h>
   #include<unistd.h>
   #include<wait.h>
   #include<stdlib.h>
   #include<string.h>
   #include<sys/types.h>
   #include<sys/stat.h>
   int main(int argc,char *argv[])
   {
   	int fd,fd2=-1;
   	int i;
   	pid_t pid,pid_wait=-1;
   	int status;
   	char *buf="2班 a 007";
   	char BUF[128]={0};
   	if((pid=fork())==-1)
   	{
   		perror("fork");
   		exit(EXIT_FAILURE);
   	}
   	if(pid==0)
   	{
   		if((fd=open("myfile",O_CREAT|O_RDWR,0777))==-1)//在子进程中打开文件
   		{
   			perror("open");
   			exit(EXIT_FAILURE);
   		} 
   		if(write(fd,buf,strlen(buf))==-1)
   		{
   			perror("write");
   			exit(EXIT_FAILURE);
   		}
   		exit(EXIT_SUCCESS);
   	}
   	else 
   	{
   		pid_wait=wait(&status);//使父进程处于阻塞状态 
   		if((WIFEXITED(status)))//判断子进程是否正常终止
   		{
   			printf("normal exit,return value:%d\n",WEXITSTATUS(status));
   		}
   		printf("child PID: %d\n",pid_wait);
   		if((fd=open("myfile",O_RDONLY))==-1)
   		{
   			perror("parent open");
   			exit(EXIT_FAILURE);
   		} 
   		if(read(fd,BUF,128)==-1)//读取文件
   		{
   			perror("read");
   			exit(EXIT_FAILURE);
   		}
   		printf("read myfile: %s\n",BUF);
   		close(fd);
   		exit(EXIT_SUCCESS);
   		}
   }

实验四,第三题
1.编写程序实现以下功能:
利用有名管道文件实现进程间通信,要求
写进程向有名管道文件写入10次“hello world”
读进程读取有名管道文件中的内容,并依次打印。
创建有名管道源码

    #include<stdio.h>
    #include<fcntl.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<sys/stat.h>
    /*
     *有名管道实现非亲缘关系的进程通信
     *进程一 向有名管道中写入数据,如果进程二不已可读方式打开管道则进程一阻塞,直到进程二以可读方式打开管道
     * */
    int main(int argc,char *argv[])
    {
    	int fd;
    	if(mkfifo("FIFO",0777)==-1)//创建有名管道
    	{
    		perror("mkfifo");
    		exit(EXIT_FAILURE);
    	}
    	printf("管道FIFO创建成功!\n");
    	return 0;
    }

2.写进程

    #include<stdio.h>
    #include<fcntl.h>
    #include<unistd.h>
    #include<stdlib.h>
    /*
     *写进程 
     * */
    int main(int argc,char *argv[])
    {	
    	int write_fd;
    	char buf[]="hello world";
    	if((write_fd=open("FIFO",O_WRONLY))==-1)
    	{
    		perror("open");
    		exit(EXIT_FAILURE);
    	}
    	for(int i=0;i<10;i++)
    	{
    		if(write(write_fd,buf,sizeof(buf)-1)==-1)
    		{
    			perror("write");
    			exit(EXIT_FAILURE);
    		}
    		usleep(10);
    	}
    	exit(EXIT_SUCCESS);
    }

读进程

   #include<stdio.h>
   #include<fcntl.h>
   #include<unistd.h>
   #include<stdlib.h>
   #include<string.h>
   /*
    *读进程 
    * */
   int main(int argc,char *argv[])
   {	
   	int read_fd;
   	char buf[128]={0};
   	if((read_fd=open("FIFO",O_RDONLY))==-1)
   	{
   		perror("open");
   		exit(EXIT_FAILURE);
   	}
   	for(int i=0;i<10;i++)
   	{
   	if(read(read_fd,buf,sizeof(buf))==-1)
   	{
   		perror("write");
   		exit(EXIT_FAILURE);
   	}
   		printf("%s\n",buf);
   		memset(buf,0,sizeof(buf));
   	}
   	exit(EXIT_SUCCESS);
   }
一. 填空题: 1.Linux系统中,以 文件 方式访问设备 。 2. Linux内核引导时,从文件 /etc/fstab 中读取要加载的文件系统。 3. Linux文件系统中每个文件用 i节点 来标识。 .... 82. 增加一个用户的命令是:adduser 或useradd 。 83 进行字符串查找,使用grep命令。 84. 使用 * 每次匹配若干个字符。 85. /sbin 目录用来存放系统管理员使用的管理程序。 二.单项选择题: 1. 下面的网络协议中,面向连接的的协议是: A 。 A 传输控制协议 B 用户数据报协议 C 网际协议 D 网际控制报文协议 2. 在/etc/fstab文件中指定的文件系统加载参数中, D 参数一般用于CD-ROM等移动设备。 ... 113.不是shell具有的功能和特点的是 C 。 A 管道 B 输入输出重定向 C 执行后台进程 D 处理程序命令 114.下列对shell变量FRUIT操作,正确的是: C 。 A 为变量赋值:$FRUIT=apple B 显示变量的值:fruit=apple C 显示变量的值:echo $FRUIT D 判断变量是否有值:[ -f “$FRUIT” ] 三.简答题: 1.简述Linux文件系统通过i节点把文件的逻辑结构和物理结构转换的工作过程。 参考答案: Linux通过i节点表将文件的逻辑结构和物理结构进行转换。 i节点是一个64字节长的表,表中包含了文件的相关信息,其中有文件的大小、文件所有者、文件的存取许可方式以及文件的类型等重要信息。在i节点表中最重要的内容是磁盘地址表。在磁盘地址表中有13个块号,文件将以块号在磁盘地址表中出现的顺序依次读取相应的块。Linux文件系统通过把i节点和文件名进行连接,当需要读取该文件时,文件系统在当前目录表中查找该文件名对应的项,由此得到该文件........ root@xxx:#crontab prgx;在每日早晨8:00之前开机后即可自动启动crontab。 6.设计一个shell程序,在每月第一天备份压缩/etc目录的所有内容,存放在/root/bak目录里,且文件名为如下形式yymmdd_etc,yy为年,mm为月,dd为日。Shell程序fileback存放在/usr/bin目录下。 参考答案: (1)编写shell程序fileback: #!/bin/sh DIRNAME=`ls /root | grep bak` if [ -z "$DIRNAME" ] ; then mkdir /root/bak cd /root/bak fi YY=`date +%y` MM=`date +%m` DD=`date +%d` BACKETC=$YY$MM$DD_etc.tar.gz tar zcvf $BACKETC /etc echo "fileback finished!" (2)编写任务定时器: echo "0 0 1 * * /bin/sh /usr/bin/fileback" >; /root/etcbakcron crontab /root/etcbakcron 或使用crontab -e 命令添加定时任务: 0 1 * * * /bin/sh /usr/bin/fileback 7.有一普通用户想在每周日凌晨零点零分定期备份/user/backup到/tmp目录下,该用户应如何做? 参考答案:(1)第一种方法: 用户应使用crontab –e 命令创建crontab文件。格式如下: 0 0 * * sun cp –r /user/backup /tmp (2)第二种方法: 用户先在自己目录下新建文件file文件内容如下: 0 * * sun cp –r /user/backup /tmp 然后执行 crontab file 使生效。 8.设计一个Shell程序,在/userdata目录下建立50个目录,即user1~user50,设置每个目录的权限,其中其他用户的权限为:读;文件所有者的权限为:读、写、执行;文件所有者所在组的权限为:读、执行。 参考答案: 建立程序 Pro16如下: #!/bin/sh i=1 while [ i -le 50 ] do if [ -d /userdata ];then mkdir -p /userdata/user$i chmod 754 /userdata/user$i echo "user$i" let "i = i + 1" (或i=$(($i+1)) else mkdir /userdata mkdir -p /userdata/user$i chmod 754 /userdata/user$i echo "user$i" let "i = i + 1" (或i=$(($i+1)) fi done
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sky-stars

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值