Linux 编程技术知识要点

Linux 编程技术知识要点

非编程题

  1. linux中把分区和目录对应的过程叫做 挂载

  2. 信号是在软件层次上对 中断 机制的一种模拟, 是一种异步通信方式。

  3. 用GCC编译过程可以被细分为四个阶段:预编译,编译,汇编,链接

  4. 编译有线程的文件要加 -lpthread 参数。

  5. 父进程等待子进程的结束,可以使用的函数 wait()waitpid()

  6. linux主要有两个信号安装函数,分别是什么signal(),sigaction()

  7. Linux操作系统内核由 C语言 编写完成。

  8. 使用gdb调试程序时,next和step命令的作用?

    step 就是单步执行,遇到子函数就进入并且继续单步执行;

    next 是在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子 函数整个执行完再停止,也就是把子函数整个作为一步。

  9. 目录 /Boot 下存放linux操作系统启动时所要用到的程序

  10. Linux 系统的设备文件分为三类?

    块设备文件,字符设备文件,网络设备文件

  11. Linux 中采用“一对一”的线程机制,也就是一个用户线程对应一个 内核线程

  12. vim三种模式:在命令模式下按下 Esc 就进入了底线命令模式。

  13. 标准I/O提供了三种类型的缓冲,分别是?

    全缓冲,行缓冲,不带缓冲

  14. linux文件系统由四部分组成:

    超级块 用于存放文件的控制信息。

    引导块:在文件系统的开头,通常为一个扇区,其中存放引导程序,用于读入并启动操作系统;

    超级块:用于记录文件系统的管理信息。特定的文件系统定义了特定的超级块;

    inode区(索引节点):一个文件或目录占据一个索引节点。第一个索引节点是该文件 系统的根节点。利用根节点,可以把一个文件系统挂在另一个文件系统的非叶节点上;

    数据区:用于存放文件数据或者管理数据。

  15. 一个完整的信号生命周期包含4个重要的事件,这4个重要事件分别是?

    信号诞生;

    信号在进程中注册完毕;

    信号在进程中的注销完毕;

    信号处理函数执行完毕。

  16. 互斥锁只有两种状态,即?上锁,解锁

  17. 线程本身调用 return 函数可以退出线程。

  18. 向消息队列发送消息的函数是 msgsnd() 接收消息的函数是 msgrcv()

  19. 系统调用可以根据文件描述符来操作文件特性。

    Valgrind包括很多工具, memcheck 是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况, cachegrind是主要用来检查程序中缓存使用出现的问题。

    ​ memcheck ------> 这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝 大多数内存错误使用情况,

    ​ callgrind ------> 它主要用来检查程序中函数调用过程中出现的问题。

    ​ cachegrind ------> 它主要用来检查程序中缓存使用出现的问题。

    ​ helgrind ------> 它主要用来检查多线程程序中出现的竞争问题。

    ​ massif ------> 它主要用来检查程序中堆栈使用中出现的问题。

    ​ extension ------> 可以利用core提供的功能,自己编写特定的内存调试工具

  20. 信号发送函数中, alarm函数用于设置定时器,当计时时间到达时,向进程发送SIGALRM信号。

  21. 在标准IO库中,rewind函数作用?

    将文件内部的位置指针重新指向一个流(数据流/文件)的开头

  22. c语言中没有明确给定初值的全局变量和静态变量存放在哪儿?

    全局存储区(静态存储区)

  23. 函数geteuid()用于得到进程的?

    当前进程的实际用户UID值

  24. 当一个线程的属性设置为 detach ,该线程结束时立即释放它所占有的系统资源。

  25. 以下哪种方式属于异常终止一个进程( D)

    A 从main函数返回。

    B 调用exit。

    C 最后一个线程从其启动例程返回。

    D 接到一个信号并终止。

  26. 下列命令哪个是创建线程私有数据命令(A)

    A pthread_key_create()

    B pthread_setspecific()

    C pthread_getspecific()

    D pthread_key_delete();

  27. 下面哪种通信方式适用于不同机器之间的进程通信。( D )

    A.消息队列

    B.共享内存

    C.信号量

    D.套接字

  28. 创建或打开消息队列的函数为(A )

    A.msgget()

    B.msgsnd()

    C.msgrcv()

    D. msgctl()

  29. 什么是进程?进程资源由哪两部分组成?

    进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础

    进程资源包括内核空间进程资源和用户空间进程资源

  30. linux中通过调用waitpid()函数得到进程的退出信息,该函数原型为pid_t waitpid(pit_t pid, int *statloc, int options);当第一个参数pid取值为-1时,表示(A)

    A 等待任一子进程退出,相当于 wait()。

    B 等待进程组ID与调用进程组ID相同的任一子进程。

    C 只等待进程ID等于PID的子进程。

    D 等待指定进程组中的进程,该进程组id等于 pid的绝对值。

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

    创建失败时返回负数;创建成功时返回两个值:父进程的fork返回一个正数表示子进程的进程ID,子进程的fork返回 0

  32. Linux环境中使用kill函数向进程或进程组发送信号。Kill函数原型为int kill(pid_t pid, int signo);当第一个参数pid>0时,表示( A )

    A 发送信号给进程ID为pid的进程;

    B 发送信号给进程组ID和该进程相同的进程;

    C 发送信号给进程组内进程ID为pid的绝对值的进程;

    D 发送信号给系统的所有进程;

    pid>0 将信号传给进程识别码为pid 的进程。
    pid=0 将信号传给和目前进程相同进程组的所有进程
    pid=-1 将信号广播传送给系统内所有的进程
    pid<0 将信号传给进程组识别码为pid绝对值的所有进程

  33. 共享主存基本操作(A )将共享主存区映射到进程虚拟地址空间。

    A shmat()

    B shmdt()共享内存

    C shmctl()控制对共享内存的使用

    D shmget() 创建共享内存

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

    A msgsnd()发送信息

    B msgctl() 控制

    C msgrcv() 获取信息

    D msgget() 创建

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

    如果其所有子进程都还在运行,则阻塞;

    如果一个子进程已经终止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回;

    如果它没有任何子进程,则立即出错返回;

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

    return是语言级别的,它表示了调用堆栈的返回;而exit是系统调用级别的,它表示一个进程的结束。

    在main函数里,return(0)和exit(0)是一样的,子函数用return返回,而子进程用exit退出,调用exit时要调用一段终止处理程序,然后关闭所有I/O流

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

    孤儿进程:因父亲进程先退出而导致一个子进程被init进程收养的进程,即孤儿进程的父亲更改为init进程,该进程在孤儿进程退出后回收它的内核空间资源。

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

    僵尸进程:进程已经退出,但它的父亲进程还没有回收内核资源的进程,即该进程在内核空间的PCB没有释放。利用kill函数杀死父进程,僵尸函数会被init进程收养

  39. 简述进程对可靠信号和不可靠信号的处理过程。

    如果进程在屏蔽某个信号的时间内,其他进程多次向其发送同一个信号,

    不可靠信号只有一次未决记录,当进程解除屏蔽后,该信号只会被捕捉一次;

    而可靠信号操作系统会记录所有的发送,当进程解除屏蔽后,操作系统会捕捉对等次数。

  40. 简单介绍一下信号的定义及其分类。

    信号是表示消息的物理量,是运载消息的工具

    信号是软件中断,是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的

    分类:

    ​ 确定信号和随机信号;

    ​ 连续信号和离散信;

    ​ 周期信号和非周期信号;

    ​ 能量信号与功率信号;

    ​ 因果信号与反因果信号;

    ​ 实信号与复信号

  41. 简单介绍一下匿名管道及其特点。

    匿名管道用于进程之间通信,且仅限于本地父子进程之间通信,结构简单。

    ​ 1)只提供单向通信,也就是说,两个进程都能访问这个文件,假设进程1往文件内写东西,那么进程2 就只能读取文件的内容。
    ​ 2)只能用于具有血缘关系的进程间通信,通常用于父子进程建通信
    ​ 3)管道是基于字节流来通信的
    ​ 4)依赖于文件系统,它的生命周期随进程的结束结束(随进程)
    ​ 5)其本身自带同步互斥效果

  42. 请解释一下有名管道和匿名管道的区别?

    匿名管道是由pipe函数创建并打开的
    命名管道是由mkfifo函数创建的 ,打开用open
    命名管道和匿名管道唯一的区别就是在创建的打开,一旦这些工作完成后,它们有相同的意义。

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

    线程是操作系统能够进行运算调度的最小单位。

    ​ 进程是运行中的程序,线程是进程的内部的一个执行序列
    ​ 进程是资源分配的单元,线程是执行行单元
    ​ 进程间切换代价大,线程间切换代价小
    ​ 进程拥有资源多,线程拥有资源少
    ​ 多个线程共享进程的资源

  44. Please describe the difference of signal() and sigaction() in brief
    翻译为:请简单描述一下signal()和sigaction()的区别

    1、signal在调用handler之前先把信号的handler指针恢复;

    sigaction调用之后不会恢复handler指针,直到再次调用sigaction修改handler指针。

    这样,signal就会丢失信号,而且不能处理重复的信号,而sigaction就可以。因为signal在得到信号和调用handler之间有个时间把handler恢复了,这样再次接收到此信号就会执行默认的handler。(虽然有些调用,在handler的以开头再次置handler,这样只能保证丢信号的概率降低,但是不能保证所有的信号都能正确处理)
    2、signal在调用过程不支持信号block;sigaction调用后在handler调用之前会把屏蔽信号(屏蔽信号中自动默认包含传送的该信号)加入信号中,handler调用后会自动恢复信号到原先的值。
    3、signal处理过程中就不能提供阻塞某些信号的功能,sigaction就可以阻指定的信号和本身处理的信号,直到handler处理结束。这样就可以阻塞本身处理的信号,到handler结束就可以再次接受重复的信号。

编程题

第一题

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

#include<stdio.h>
#include<fcntl.h>
int main(){
    
    
    int fd1,fd2;
    char str[14];
    fd1 = open("file1.txt",O_RDWR|O_CREAT);
    if(fd1 < 0)
        perror("open file1 error");
    write(fd1,"abcdefghijklmn",14);
    lseek(fd1,0,SEEK_SET);
    fd2 = open("file2.txt",O_RDWR|O_CREAT);
    if(fd2 < 0)
        perror("open file2 error");
    write(fd2,"ABCDEFGHIJKLMN",14);
    read(fd1,str,14);
    write(fd2,str,14);
    close(fd1);
    close(fd2);
    return 0;
}

第二题

1.创建新文件,该文件具有用户读写权限。
2.采用dup/dup2/fcntl复制一个新的文件描述符,通过新文件描述符向文件写入“class_name”字符串;
3.通过原有的文件描述符读取文件中的内容,并且打印显示;

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
int main(int argc,char argv[]){
    
    
        int fd;
        fd = open("test2.file",O_CREAT|O_WRONLY,S_IREAD|S_IWRITE);
        char *name="class_name";
        int fd2 = dup(fd);
        if(fd2<0)
                perror("dup");
        write(fd2,name,strlen(name));
        lseek(fd,0,SEEK_SET);
        char str[12];
        read(fd,str,12);
        printf("%s\n",str);
        close(fd);
        return 0;
}

第三题

1.递归遍历/home目录,打印出所有文件和子目录名称及节点号。
2.判断文件类型,如果是子目录,继续进行递归遍历,直到遍历完所有子目录为止。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
int show (char * path){
    
    
    char p[500];
    DIR *dir;
    struct stat statbuf;
    struct dirent *dire;
    lstat (path,&statbuf);
    if (S_ISDIR(statbuf.st_mode)){
    
    
         dir = opendir (path);
         if (dir){
    
    
            while( (dire = readdir(dir) ) !=NULL)
               {
    
    
                 if(( dire ->d_name[0] )=='.')
                    continue;
                 sprintf(p,"%s/%s",path,dire->d_name);
                 lstat(p,&statbuf);
                 printf ("\t该目录文件名为: %s \n",p);
                 printf ("\t该目录文件节点号为: %ld \n",statbuf.st_ino);
                 show (p);
               }
         }
       }
    if (S_ISREG(statbuf.st_mode))//判断文件是否为常规文件
     {
    
    
         printf ("该文件名为: %s \n",path);//输出文件名
         printf ("该文件节点号为: %ld \n",statbuf.st_ino);
       }
 }
int main(){
    
    
        show("/home");
        return 0;
 }

第四题

1.打印字符串“hello world!”
2.在打印字符串“hello world!”前调用三次fork,分析打印结果。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
    
    
	int i;
 	for(i=0;i<3;i++)
	{
    
    
		fork(); 
	}
	printf("hello world!!!\n");
	return 0;
}

第五题

创建子进程

1.在子进程中打开文件file,写入自己的“班级_姓名_学号”,

2.父进程读取file中的内容,并且打印显示。

3.在父进程中获取已经结束的子进程的状态信息,打印该信息,并且打印结束的子进 程的进程号。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
int main(){
    
    
	int fd,pid;
	fd = open("file.txt",O_CREAT|O_RDWR,S_IRWXU);
	if(fd< 0)
	  perror("open");
	pid = fork();
	if(pid  == 0){
    
    
		printf("This is the child!\n");
		char str[128] = "yidongsanban_jjj_1101010";
		if(write(fd,str,128) < 0)
		  perror("write");
		exit(5);
	}
	else{
    
    
		printf("This is the father!\n");
		
		char buf[128];
		int n,status;
		if(read(fd,buf,128) < 0)
		  perror("read");
		printf("The buf is: %s\n",buf);
 
		if(wait(&status) < 0)
		  perror("perror");
 
		if(WIFEXITED(status))
		  n = WEXITSTATUS(status);
		else
		  printf("wait error!\n");
 
		printf("The child's pid is: %d\n",pid);
		printf("The child exit status is: %d\n",n);
	}
	return 0;
}

第六题

利用有名管道文件实现进程间通信,要求

写进程向有名管道文件写入10次“hello world”;

读进程读取有名管道文件中的内容,并依次打印。

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
int main() {
    
    
	int pid,fd,i;
	if(mkfifo("fifotest",0666) < 0)
		perror("mkfifo");

	pid = fork();

	if(pid < 0)
		perror("fork");
	else if(pid == 0) {
    
    
		printf("This is the write process!\n");
		int fd = open("fifotest",0666);

		for(i = 0; i < 10; i++) {
    
    
			if(write(fd,"hello world",12) < 0)
				perror("write");
			sleep(1);
		}
		close(fd);
	} else {
    
    
		char str[128];
		printf("This is the read process!\n");
		int fd1 = open("fifotest",0666);

		for(i = 0; i < 10; i++) {
    
    
			if(read(fd1,str,128) < 0)
				perror("read");
			else
				printf("%s\n",str);
		}
		system("rm -f fifotest");
	}
}

猜你喜欢

转载自blog.csdn.net/qq_46036214/article/details/111653961