Linux编程技术作业

Linux编程技术

作业1

  1. 编写一个简单的c语言程序:输出两行文字“Linux下的c也不是太难嘛!”,在Linux下编辑、编译、运行。

    [jia@localhost ~]$ cd Desktop/924/1

    [jia@localhost 1]$ vi 1.c

    [jia@localhost 1]$ gcc -c 1.c

    [jia@localhost 1]$ ls

    1.c 1.o

    [jia@localhost 1]$ gcc -o 1 1.o

    [jia@localhost 1]$ ls

    1 1.c 1.o

    [jia@localhost 1]$ ./1

    Linux下的c也不是太难嘛!

    1.jpg

  2. 编写一个简单的c语言程序:根据输入的两个整数求平均值并且在终端输出,通过gcc编译器得到它的汇编程序文件。

    [jia@localhost ~]$ cd Desktop/924/2

    [jia@localhost 2]$ vi 2.c

    [jia@localhost 2]$ vi 2.c

    [jia@localhost 2]$ gcc 2.c -o 2

    [jia@localhost 2]$ ./2

    请输入x的值: 5

    请输入y的值: 7

    平均值:6

    2.jpg

  3. 用gdb调试器调试上面第2题的程序,查看程序执行每一步变量的值,熟悉gdb的使用流程。

[jia@localhost 2]$ gdb 2

GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6)

Copyright © 2010 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law. Type “show copying”

and “show warranty” for details.

This GDB was configured as “i686-redhat-linux-gnu”.

For bug reporting instructions, please see:

http://www.gnu.org/software/gdb/bugs/

Reading symbols from /home/jia/Desktop/924/2/2…done.

(gdb) r

Starting program: /home/jia/Desktop/924/2/2

请输入x的值: 5

请输入y的值: 7

平均值:6

Program exited normally.

Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.107.el6.i686

(gdb) break 9

Breakpoint 1 at 0x804844f: file 2.c, line 9.

(gdb) r

Starting program: /home/jia/Desktop/924/2/2

Breakpoint 1, main () at 2.c:9

9printf("请输入x的值: ");

(gdb)

(gdb) r

The program being debugged has been started already.

Start it from the beginning? (y or n) y

Starting program: /home/jia/Desktop/924/2/2

Breakpoint 1, main () at 2.c:9

9printf("请输入x的值: ");

(gdb) n

10scanf("%d",&x);

(gdb) n

请输入x的值: 5

11printf("请输入y的值: ");

(gdb) n

12scanf("%d",&y);

(gdb) n

请输入y的值: 7

13 avg(x,y);

(gdb) n

平均值:6

14 return 0;

3.jpg

  1. 编写一个c语言程序:实现简单的计算器的功能(至少有加法、减法操作,每个功能封装成函数)。

    [jia@localhost 924]$ cd 4

    [jia@localhost 4]$ ./main

    1 加法运算

    2 减法运算

    3 乘法运算

    4 除法运算

    请选择: 3

    请输入a和b的值: 5 6

    5 * 6 = 30

    4.jpg这是源码:
    链接:https://pan.baidu.com/s/1tECUwC5t-csz5LXEZw2i4Q
    提取码: x966

  2. 请将第四题封装成静态库和动态库,使用测试程序来连接该库函数,并运行出相应的结果。

    静态库:

    [jia@localhost 924]$ cd 5

    [jia@localhost 5]$ cd jt

    [jia@localhost jt]$ gcc -o add.o -c add.c

    [jia@localhost jt]$ gcc -o mul.o -c mul.c

    [jia@localhost jt]$ ar rcs libmyku.a add.o mul.o

    [jia@localhost jt]$ gcc hello.c libmyku.a -o hello

    [jia@localhost jt]$ ./hello

    5 + 3 = 8

    5 - 3 = 2

    jingtai.jpg

    动态库:

    [jia@localhost jt]$ gcc -o add.o -c add.c

    [jia@localhost jt]$ gcc -o mul.o -c mul.c

    [jia@localhost jt]$ ar rcs libmyku.a add.o mul.o

    [jia@localhost jt]$ gcc hello.c libmyku.a hello

    gcc: hello: No such file or directory

    [jia@localhost jt]$ gcc hello.c libmyku.a -o hello

    [jia@localhost jt]$ ./hello

    5 + 3 = 8

    5 - 3 = 2

    [jia@localhost jt]$ ^C

    [jia@localhost jt]$ cd -

    /home/jia/Desktop/924/5

    [jia@localhost 5]$ cd dt/

    [jia@localhost dt]$ gcc -o add.o -c add.c -fPIC

    [jia@localhost dt]$ gcc -o mul.o -c mul.c -fPIC

    [jia@localhost dt]$ gcc -shared -o libmyku.so add.o mul.o

    [jia@localhost dt]$ gcc hello.c -o hello -l myku -L .

    [jia@localhost dt]$ export LD_LIBRARY_PATH=.

    [jia@localhost dt]$ ./hello

    5 + 3 = 8

    5 - 3 = 2

    dongtai.jpg

    分析

    静态库的制作

    1. 将源文件.c文件生成.o文件
      gcc -o add.o -c add.c
    2. 使用ar工具制作静态库
      ar rcs lib库名.a .o文件
      例:ar rcs libmyku.a add.o mul.o …
    3. 编译静态库到可执行文件中,否则链接出错
      gcc hello.c libmyku.a -o hello (编译时, 库放在后面)

    动态库的制作

    1. 将源文件.c文件生成.o文件 (生成与位置无关的代码 -fPIC)
      gcc -o add.o -c add.c -fPIC
    2. 使用gcc -shared 工具制作动态库
      gcc -shared lib库名.so .o文件
      例: gcc -shared -o libmyku.so add.o mul.o
    3. 编译动态库到可执行文件中, -l 指定库名(去掉lib前缀和.so后缀) -L 指定库路径
      gcc hello.c -o hello -l myku -L .
      注:配置环境变量
      export LD_LIBRARY_PATH=.
      export LD_LIBRARY_PATH=/home/jia/Desktop/lib/dT/

作业2-文件系统

  1. linux文件系统通常由四部分组成:引导块,超级块,索引节点和 。

    • A、文件块
    • B、数据块
    • C、索引块
    • D、目录块
  2. 任何进程在运行时默认打开的三个流对象,都有相应的文件描述符,标准文件描述符定义标准输入设备的值为 。

    • A、0
    • B、1
    • C、2
    • D、3
  3. *系统调用的函数原型int open(const char pathname, int flags),flag值中 表示以读写的方式打开文件。

    • A、O_RDONLY
    • B、O_WRONLY
    • C、O_RDWR
    • D、O_APPEND
  4. *系统调用的函数原型int open(const char pathname, int flags),flag值中 表示若文件存在且为只读或只写成功打开,则将长度截为0。

    • A、O_APPEND
    • B、O_TRUNC
    • C、O_CREAT
    • D、O_EXCL
  5. 代码

    #include<stdio.h>
    #include<stdlib.h>
    #include<fcntl.h>
    #include<unistd.h>
    #include<string.h>
    
    int main(){
          
          
    	;
    	int fd,length;
    	fd=open("lseek.txt",O_RDWR);
    	length=lseek(fd,0,SEEK_END);
    	printf("the length os lseek is %d\n",length);
    	close(fd);
    	
    	return 0;
    }
    

    此行代码length=lseek(fd,0,SEEK_END);中的length的值表示 。

    • A、文件lseek.txt的大小 A
    • B、调整lseek.txt指针位置到文件的开头
    • C、调整lseek.txt指针位置到文件的中间
    • D、调整lseek.txt指针位置到文件的第二个字节
  6. 使用下列函数调用int fcntl(int fd, int cmd);来实现文件描述符的复制,cmd参数应使用哪一个?

    • A、F_DUPFD
    • B、FD_CLOEXEC
    • C、F_GETFD
    • D、F_SETFD
  7. **阅读程序填空:如果想要获取文件的大小,空白处应该填写以下哪个答案。A**

    #include<stdio.h>
    #include<unistd.h>
    #include<sys/stat.h>
    
    int main(int argc, char *argv[]){
          
          
    
    	struct stat statBuf;
    	if(stat(argv[1],&statBuf)<0){
          
          
    		perror("stat");
    	}else{
          
          
    		printf("the size of file is %ld",       );
    	}
    	return 0;
    }
    
    • A、statBuf.st_size
    • B、statBuf.st_ino
    • C、statBuf.st_ctime
    • D、statBuf.st_atime
  8. 在创建文件和目录时候,有默认权限。如果umask值为0022,则文件的默认权限为 B

    • A、0666
    • B、0644
    • C、0777
    • D、0755
  9. 代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    int main (void){
          
          
    	int fd;
    	if((fd=open("tempfile",O_WRONLY|O_CREAT|O_TRUNC,0700))< 0){
          
          
    		perror("open");
        	exit(1);
    	}
    	if((link("tempfile","hardlink"))==-1){
          
          
    		perror("open");
    		exit(1);
    	}
    	struct stat statBuf;
    	fstat(fd, &statBuf);
    	printf("link num:%ld\n", statBuf.st_nlink);
    	sleep(3);
    	if(unlink("tempfile") < 0){
          
          
    		perror("unlink");
    		exit(1);
    	}
    	fstat(fd, &statBuf);
    	printf("unlink ,num:%ld\n", statBuf.st_nlink);
    	return 0;
    }
    

    执行程序,代码输出结果为 A

    • A、link num:2

      ​ unlink ,num:1

    • B、link num:2

      ​ unlink ,num:2

    • C、link num:3

      ​ unlink ,num:2

    • D、link num:1

      ​ unlink ,num:1

  10. 获取目录的系统调用函数为 B

    • A、chdir()
    • B、getcwd()
    • C、opendir
    • D、closedir

作业3-线程

  1. 下述是Linux下多线程编程常用的pthread库提供的函数名和意义,说法不正确的是D
    • A、pthread_create 创建一个线程
    • B、pthread_join用来等待一个线程的结束
    • C、pthread_mutex_init 初始化一个线程互斥锁
    • D、pthread_exit杀死一个线程
  2. 对线程函数来说,说法正确的是:A
    • A、pthread_create中参数arg是传递给start_routine函数的参数
    • B、pthread_join函数用于结束线程,其参数是线程的返回值
    • C、pthread_exit函数用于退出另一个线程,参数是另一个线程的ID
    • D、pthread_cancel函数用于取消当前线程的执行,即退出本线程
  3. 对互斥锁及条件变量说法不正确的是: D
    • A、互斥锁保证让每个线程对共享资源按顺序进行原子操作
    • B、条件变量是让线程睡眠,在符合某种条件时唤醒睡眠的线程
    • C、条件变量可以让多个线程在某一时间上保持同步
    • D、在使用条件变量时,互斥锁会失去作用,所以是否有互斥锁关系不重要
  4. 以下说明正确的是:B
    • A、进程和线程都可以由CPU直接执行的指令流,所以进程和线程没有区别
    • B、线程是一个独立的指令流,是在进程中被创建的,随进程的关闭而关闭
    • C、进程和线程都是一个程序,是执行程序的过程,拥有完整的资源,都有自己的数据段、代码段等
    • D、一个回调函数就是一个线程,所以多线程必须有多个回调函数实现
  5. 线程A SendMessage给线程B,线程B处理该消息时又SendMessage给线程A,会出现:B
    • A、死锁
    • B、继承执行
    • C、线程A停止响应
    • D、线程B停止响应

作业4-进程

  1. 一个进程是 ( C )。

    • A、处理机一次或多次执行的一个程序。
    • B、一个独立的程序 +数据集。
    • C、PCB 结构与程序和数据的组合。
    • D、一个独立的程序。
  2. 一个进程调用 wait 或 waitpid 函数,可能产生 3 中情况,下列不属于这 3 种
    情况的是 ( D )。

    • A、如果所有子进程都还在运行,进程挂起。
    • B、如果恰有子进程结束,它的终止状态字正等待父进程提取,立即得到该
      终止状态字并返回,其返回值为该子进程的进程号。
    • C、waitpid,如果该进程没有子进程,参3指定了WNOHANG,返回0。
    • D、如果该进程没有子进程,立即返回,返回值为 0。
  3. 返回调用进程的进程标识号的系统函数是 ( A )。

    • A、getpid
    • B、getpgrp
    • C、getppid
    • D、setpid
  4. 程序和进程是两个不同的概念,以下不能描述这个观点的是 ( B )。

    • A、程序指出了处理器执行操作的步骤,而进程是一个程序在一个数据集合上
      的一次执行。
    • B、同一个程序运行 10 次,产生的是同一个进程。
    • C、进程是动态的,是程序的执行过程。
    • D、多个不同的进程可以包含相同的程序。
  5. Fork 函数在父进程中的返回值是 ( A )。

    • A、创建的子进程的进程标识号
    • B、0
    • C、-1
    • D、1
  6. 在 Linux 中,下列不属于正常结束进程的方法是 ( D )。

    • A、在 main 函数中调用 return 。
    • B、调用 exit 函数 。
    • C、调用_exit 函数 。
    • D、调用 abort函数。
  7. 以下程序的输出结果是( B

    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <pthread.h>
    int main(int argc, char *argv[]) {
          
          
    	printf("===================start of file\n");
    	pid_t pid = fork();
    	if (pid == -1) {
          
          
    		perror("fork error");
    		exit(1);
    	} else if (pid == 0) {
          
          
    		printf("---child,my pid is %d,my parent pid is %d\n",getpid(),getppid());
    	} else if (pid > 0) {
          
          
    		printf("---parent my child is %d,my pid is %d,myparent pid is %d\n", pid,getpid(),getppid());
    		sleep(1);
    	}
    	printf("===================end of file\n");
    
    	return 0;
    }
    
    • A、

      ===================start of file

      —parent my child is 4759,my pid is 4758,myparent pid is 3700

      —child,my pid is 4759,my parent pid is 4758

      ===================end of file

    • B、

      ===================start of file

      —parent my child is 4759,my pid is 4758,myparent pid is 3700

      —child,my pid is 4759,my parent pid is 4758

      ===================end of file

      ===================end of file

    • C、

      ===================start of file

      —parent my child is 4759,my pid is 4758,myparent pid is 3700

      —child,my pid is 4759,my parent pid is 4758

      ===================end of file

      ===================end of file

      ===================end of file

    • D、

      ===================start of file

      ===================start of file

      —parent my child is 4759,my pid is 4758,myparent pid is 3700

      —child,my pid is 4759,my parent pid is 4758

      ===================end of file

      ===================end of file

      运行截图

      image-20201207125829919

  8. 以下程序输出结果是( C

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    int var = 100;
    int main(void) {
          
          
    	pid_t pid;
    	pid = fork();
    	if (pid == -1) {
          
          
    		perror("fork error");
    		exit(1);
    	} else if (pid > 0) {
          
          
    		var = 288;
    		printf("parent, var = %d\n", var);
    		sleep(1);
    	} else if (pid == 0) {
          
          
    		printf("child, var = %d\n", var);
    	}
    	printf("------------finish---------------\n");
    
    	return 0;
    }
    
    • A、

      parent, var = 288

      child, var = 100

      ------------finish---------------

    • B、

      parent, var = 288

      child, var =288

      ------------finish---------------

      ------------finish---------------

    • C、

      parent, var = 288

      child, var = 100

      ------------finish---------------

      ------------finish---------------

    • D、

      parent, var = 288

      child, var = 288

      ------------finish---------------

      ------------finish---------------

      运行截图

      image-20201207125925641

  9. 以下程序输出结果是( A

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    int var = 100;
    int main(void) {
          
          
    	int *p;
    	pid_t pid;
    	int fd;
    	fd = open("temp", O_RDWR|O_CREAT|O_TRUNC, 0644);
    	if(fd < 0) {
          
          
    		perror("open error");
    		exit(1);
    	}
    	ftruncate(fd, 4);
    	p = (int *)mmap(NULL, 4, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
    	if(p == MAP_FAILED) {
          
          
    		perror("mmap error");
    		exit(1);
    	}
    	close(fd);
    	pid = fork();
    	if(pid == 0) {
          
          
    		*p = 7000;
    		var = 1000;
    		printf("child, *p = %d, var = %d\n", *p, var);
    	} else {
          
          
    		sleep(1);
    		printf("parent, *p = %d, var = %d\n", *p, var);
    		wait(NULL);
    		int ret = munmap(p, 4);
    		if (ret == -1) {
          
          
    			perror("munmap error");
    			exit(1);
    		}
    	}
    	return 0;
    }
    
    • A、

      child, *p = 7000, var = 1000

      parent, *p = 0, var = 100

    • B、

      child, *p = 7000, var = 1000

      parent, *p = 7000, var = 100

    • C、

      child, *p = 7000, var = 1000

      parent, *p = 7000, var = 1000

    • D、

      child, *p = 7000, var = 1000

      parent, *p = 0, var = 1000

      运行截图

      image-20201207130556354

  10. 哪种进程之间的通信,数据不可以重复读( B C

    • A、共享内存映射进程间通信
    • B、fifo
    • C、管道
    • D、文件

猜你喜欢

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