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);
   }
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

sky-stars

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

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

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

打赏作者

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

抵扣说明:

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

余额充值