Linux程序设计 课后习题答案
开学考试的练习。老师居然不给答案,那只能自己上了。因为个人能力有限,选择题部分可能有错误。编程题部分,确保已经在linux上运行通过后且无误后才贴上来。
第一章
简答题
3.简述系统调用和库函数区别
系统调用是直接调用linux系统中的接口,库函数则是调用c语言库中的接口。
第二章
填空题
1.vi 三种工作模式(命令模式,插入模式,末行模式)
2.gcc生成可执行文件四个过程(预处理,编译,汇编,连接)
5,库分为(静态库,共享库) 我还是比较习惯叫动态库,不过考试嘛,没法。
编程题
2.编写一个makefile,自动编译当前目录下全部的c文件。(完整题目太长了,就不写了)
OURCE=$(wildcard *.c)
OBJECT=$(patsubst %.c,%.o,$(SOURCE))
%:%.c
cc $^ -o $@
all:${OBJECT}
clean:
rm -f ${OBJECT}
第三章
编程题
2.获取当前系统时间,并按命令data的显示方式打印出来。
#include<stdio.h>
#include<time.h>
int main(){
size_t nowtime;
time(&nowtime);
struct tm *nowtime1 = localtime(&nowtime);
printf("%d %d %d %d %d %d %d ",nowtime1->tm_year+1900,
nowtime1->tm_mon+1,nowtime1->tm_mday,nowtime1->tm_wday,
nowtime1->tm_hour,nowtime1->tm_min,nowtime1->tm_sec); //简单的搞一下了
}
3.获取用户输入的年月日分秒,并设置为系统时间
(玄学修改,因为我linux上已经有服务接管时间控制,会导致修改了马上又被改会去)
#include<stdio.h>
#include<time.h>
#include <sys/time.h>
int main(){
struct tm time_tm;
struct timeval time_tv;
time_t timep;
scanf("%d-%d-%d %d:%d:%d", &time_tm.tm_year, &time_tm.tm_mon,
&time_tm.tm_mday, &time_tm.tm_hour, &time_tm.tm_min,
&time_tm.tm_sec);
time_tm.tm_year -= 1900;
time_tm.tm_mon -=1;
timep = mktime(&time_tm);
time_tv.tv_sec = timep;
time_tv.tv_usec =0;
settimeofday(&time_tv,NULL);
}
第四章
选择题
2.linux文件系统的根目录的i节点号为(2)
4.设置文件偏移量的系统调用是(lseek)
5.哪一个不是lseek第三个参数的取值(SEEK_NOW)
简答题
3.读程序,写出执行结果,并解释得到该结果的原因。
int main(){
int fd1,fd2;
fd1 = open("/etc/passwd",O_RDONLY);
fd2 = open("/etc/passwd",O_RDWR);
printf("%d %d",fd1,fd2);
}
```bash
结果为3 -1.因为第一个成功读取,第二个因为linux普通用户没有写权限所以返回-1
编程题
6.实现 cp 源文件 目标文件
#include<stdio.h>
#include<time.h>
#include <sys/time.h>
#include<stdlib.h>
#include<fcntl.h>
void cp(char *,char *);
int main(int argc , char **argv){
if(argc != 3){
exit(1);
}
cp(*(argv+1),*(argv+2));
}
void cp(char *from,char *to){
char buf[20];
int from_fd = -1, to_fd = -1;
ssize_t nread;
if((from_fd = open(from,O_RDWR) )== -1){
printf("fail open 1");
exit(1);
}
if((to_fd = open(to ,O_RDWR| O_CREAT ,0777)) == -1){
printf("fail open 2");
exit(1);
}
//printf("3");
nread = read(from_fd,buf,sizeof(buf));
while(nread > 0){
if(write(to_fd,buf,nread) != nread)
printf("write %s error",to_fd);
nread = read(from_fd,buf,sizeof(buf));
}
close(from_fd);
close(to_fd);
return;
}
第五章
编程题
2.实现“ls -l 文件名”功能
#include<stdio.h>
#include<time.h>
#include <sys/time.h>
#include<stdlib.h>
#include<fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
int fl_date(char *);
int main(int argc, char const *argv[])
{
if(argc !=3 | (strcmp(argv[1],"-l")!=0))
error(1);
fl_date(argv[2]);
}
int fl_date(char *file){
struct stat fl_stat;
struct passwd *user;
struct group *grp;
int t;
t = stat(file,&fl_stat);
if(t == -1)
exit(1);
//print
if(S_ISREG(fl_stat.st_mode)) //文件类型
printf("-");
else if(S_ISDIR(fl_stat.st_mode))
printf("d");
else if(S_ISCHR(fl_stat.st_mode))
printf("l");
else
printf("e"); //好多,摸了
putchar(fl_stat.st_mode & S_IRUSR ? 'r' : '-'); //权限
putchar(fl_stat.st_mode & S_IWUSR ? 'r' : '-');
if(fl_stat.st_mode & S_IXUSR)
putchar(fl_stat.st_mode & S_IXUSR ? 's':'S');
else
putchar(fl_stat.st_mode & S_IXUSR ? 'x':'-');
putchar(fl_stat.st_mode & S_IRGRP ? 'r' : '-');
putchar(fl_stat.st_mode & S_IWGRP ? 'r' : '-');
if(fl_stat.st_mode & S_ISGID)
putchar(fl_stat.st_mode & S_IXGRP ? 's':'S');
else
putchar(fl_stat.st_mode & S_IXGRP ? 'x':'-');
putchar(fl_stat.st_mode & S_IROTH ? 'r' : '-');
putchar(fl_stat.st_mode & S_IWOTH ? 'r' : '-');
if(fl_stat.st_mode & S_ISVTX)
putchar(fl_stat.st_mode & S_IXOTH ? 's':'S');
else
putchar(fl_stat.st_mode & S_IXOTH ? 'x':'-');
printf(" %u",fl_stat.st_nlink); //拥有者,拥有组
user = getpwuid(fl_stat.st_uid);
printf(" %s",user->pw_name);
grp = getgrgid(fl_stat.st_gid);
printf(" %s",grp->gr_name);
printf(" %u",fl_stat.st_size); //大小和时间
printf(" %s",ctime(&(fl_stat.st_ctime)));
}
第六章
编程题
7.实现”cp 目录 目录“功能,不必处理符号链接,硬链接,不必保持所有权限,时间。
#include<stdio.h>
#include<time.h>
#include <sys/time.h>
#include<stdlib.h>
#include<fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include<dirent.h>
void cp_dir(char *,char *);
int main(int argc, char const *argv[])
{
if(argc != 4 || strcmp(argv[1],"-r")) //cp -r 目录 目录
exit(1);
cp_dir(argv[2],argv[3]);
return 0;
}
void cp_dir(char *from, char *to){
int f_from,f_to;
struct stat s_from,s_to;
char buf[256];
int nread;
if((f_from = open(from,O_RDWR)) == -1)
exit(1);
if((f_to = open(to,O_RDWR | O_CREAT | O_TRUNC)) == -1)
exit(1);
nread = read(f_from,buf,sizeof(buf));
while (nread > 0)
{
if(write(f_to,buf,sizeof(buf)) == -1);
exit(1);
nread = read(f_from,buf,sizeof(buf));
}
close(f_from);
close(f_to);
}
第七章
编程题
1.使用fork创建进程,在子进程中打印“ i an the child"和pid,在父进程打印“ i an the father"和pid。
#include<stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include<time.h>
#include <sys/time.h>
#include<stdlib.h>
#include<fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include<dirent.h>
void cp_dir(char *,char *);
int main(int argc, char const *argv[])
{
pid_t pid;
pid = fork();
if(pid == -1)
exit(1);
if(pid == 0){
printf("i am chrild, my pid is %d\n",getpid());
}
else
{
printf("i am father,my pid is %d\n",getpid());
}
return 0;
}
2.创建子进程,在子进程中执行”ps -A“命令,父进程等待子进程结束后打印”child over“,已经子进程的进程号。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
pid_t pid;
pid_t child_pid;
pid = fork();
if(pid == -1)
perror(1);
else if(pid == 0){
execlp("ps","-A");
// printf("child pid is %d\n",getpid());
}
else{
wait(pid);
printf("child over.child pid is %d",pid);
}
return 0;
}
第八章
习题
试写出下列程序端的运行结果,并解释原因
#include<stdio.h>
#include <unistd.h>
#include <pthread.h>
int x=0;
int y=0;
void thread1(void);
void thread2(void);
int main(int argc, char const *argv[])
{
pthread_t id1,id2;
pthread_create(&id1,NULL,(void *)thread1,NULL);
pthread_create(&id2,NULL,(void *)thread2,NULL);
pthread_join(id1,NULL);
pthread_join(id2,NULL);
printf("x = %d ,y = %d\n",x,y);
}
void thread1(void){
printf("p1 s1\n");
y = 7;
sleep(1);
printf("p1 s2\n");
x= x+y;
}
void thread2(void){
printf("p2 s1\n");
x = 4;
sleep(1);
printf("p2 s2");
y = 8 + y;
}
结果和原因
p1 s1
p2 s1
p1 s2
p2 s2
x=11,y=15
线程1执行sleep(1);后阻塞,线程2继续执行,线程2执行到sleep(1);时线程2阻塞,线程1阻塞结束继续执行,线程1执行结束后线程继续执行到结束。
第九章
编程题
3.使用pipe实现父进程向子进程发送“1234567890”。子进程接收并显示。
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<unistd.h>
#include<sys/stat.h>
#include<stdlib.h>
int main(int argc, char const *argv[])
{
int fds[2];
pid_t pid;
char data[11] = "1234567890";
char buf[100];
if(pipe(fds) == 0){
pid = fork();
if(pid == 0){
sleep(1);
close(fds[1]);
read(fds[0],buf,sizeof(buf));
printf("i am son. %s",buf);
}
else{
close(fds[0]);
write(fds[1],data,sizeof(data));
wait(NULL);
}
}
}
6.编写程序pro21.c和pro22.c,使用命名管道实现pro21向pro22发送“abcdefg”,pro22接收并显示。
pro21.c
#include<unistd.h> //pro21.c
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
int main(int argc, char const *argv[])
{
int fd;
//int rtn;
char buf[50] = "abcdefg";
if(mkfifo("fifo.file",0777) == -1){
printf("1");
exit(1);
}
if((fd = open("fifo.file",O_RDWR)) == -1){
printf("2");
exit(1);
}
printf("writing");
write(fd,buf,sizeof(buf));
pause();
return 0;
}
pro22.c
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char const *argv[])
{
int fd;
char data[50];
if((fd = open("fifo.file",O_RDWR)) == -1)
exit(1);
if(read(fd,data,sizeof(data))==-1)
exit(1);
printf("get %s",data);
return 0;
}
第十章
编程题
2.分别利用共享内存和消息队列实现Sender向Receiver发送hello IPC
共享内存
#include<unistd.h> //Sender
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int main(int argc, char const *argv[])
{
char data[20] = "hello IPC";
key_t key;
int shmid;
void * shmptr;
key = ftok("/tmp",1);
if(key == -1){
printf("key == -1\n");
exit(1);
}
shmid = shmget(key,4096,IPC_CREAT | IPC_EXCL | 0600);
if(shmid == -1){
printf("shmid == -1\n");
exit(1);
}
shmptr = shmat(shmid,0,0);
memcpy(shmptr,data,strlen(data));
//记得最后释放共享内存。linux命令ipcrm,或在shmctl函数
}
#include<unistd.h> //Receiver
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<string.h>
int main(int argc, char const *argv[])
{
char data[20];
key_t key;
int shmid;
void * shmptr;
key = ftok("/tmp",1);
shmid = shmget(key,0,SHM_R | SHM_W);
shmptr = shmat(shmid,0,0);
memcpy(data,shmptr,strlen(shmptr)+1);
printf("%s",data);
}
第十一章
编程题
3.编程实现客户的向服务端请求某文件内容,文件名由客户端发送给服务器,服务器收到后会将对应的文件发给客户端,客户的保存文件内容。
服务端
#include<sys/socket.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<string.h>
#include<fcntl.h>
#define SERVPORT 3333
#define MAXBUF 1024
#define MAX_CONNECT 50
char buf[MAXBUF];
char file_path[MAXBUF];
void set_myaddr(struct sockaddr_in *server_addr,int protocol,int port,char* addr);
void set_file_path(char* filepath ,char* filename);
int main(int argc , char ** argv){
int sockfd,connfd,filefd;
int file_read_size;
struct sockaddr_in server_addr,client_addr;
if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){
perror("socket");
exit(1);
}
set_myaddr(&server_addr,AF_INET,SERVPORT,"127.0.0.1");
if(bind(sockfd,(struct sockaddr*)&server_addr,sizeof(struct sockaddr)) == -1){
perror("bind");
exit(1);
}
if(listen(sockfd,MAX_CONNECT) ==-1){
perror("listen");
exit(1);
}
while(1){
int client_size = sizeof(struct sockaddr_in);
if((connfd = accept(sockfd,(struct sockaddr*)&client_addr,&client_size)) ==-1){
perror("accept");
exit(1);
}
recv(connfd,buf,MAXBUF,0);
set_file_path(file_path,buf);
if((filefd = open(file_path,O_RDWR)) == -1){ //是否找到文件
send(connfd,"-1",sizeof("-1"),0);
close(connfd);
close(filefd);
continue;
}else
send(connfd,"1",sizeof("1"),0);
while((file_read_size = read(filefd,buf,MAXBUF)) > 0){ //发送文件
send(connfd,buf,file_read_size,0);
}
close(filefd);
close(connfd);
}
}
void set_myaddr(struct sockaddr_in *server_addr,int protocol,int port,char* addr){
server_addr->sin_family = protocol;
server_addr->sin_port = htons(port);
server_addr->sin_addr.s_addr = inet_addr(addr);
bzero(server_addr->sin_zero,8);
}
void set_file_path(char* filepath ,char* filename){ //先默认到./目录
strcpy(filepath,"./");
strcat(filepath,filename);
}
客户端
#include<sys/socket.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<string.h>
#include<fcntl.h>
#define SERVPORT 3333
#define MAXBUF 1024
char buf[MAXBUF];
void set_serveraddr(struct sockaddr_in *server_addr,int protocol,int port,char* addr);
void set_file_path(char* filepath ,char* filename);
int main(int argc , char ** argv){
int sockfd,connfd,filefd;
int file_read_size;
struct sockaddr_in server_addr;
if(argc != 3 || (strcmp(argv[1],"--get")!=0)){ // 使用 --get 文件名
printf("Invalid Argument\n");
exit(1);
}
if((sockfd = socket(AF_INET,SOCK_STREAM,0))== -1){
perror("socket error");
exit(1);
}
set_serveraddr(&server_addr,AF_INET,SERVPORT,"127.0.0.1");
if((connect(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr)))==-1){
perror("connect error");
exit(1);
}
strcpy(buf,argv[2]);
if((send(sockfd,buf,strlen(buf),0)) == -1){
perror("send error");
exit(1);
}
recv(sockfd,&buf,sizeof(buf)-1,0);
if(strcmp(buf,"-1")==0)
printf("NO FILE\n");
else if(strcmp(buf,"1")==0)
printf("FIND\n");
set_file_path(buf,argv[2]);
if((filefd = open(buf,O_RDWR | O_CREAT,0777)) == -1){
perror("open");
exit(1);
}
while((file_read_size = recv(sockfd,buf,MAXBUF,0))>0){ //接收文件
write(filefd,buf,file_read_size);
}
}
void set_serveraddr(struct sockaddr_in *server_addr,int protocol,int port,char* addr){
server_addr->sin_family = protocol;
server_addr->sin_port = htons(port);
server_addr->sin_addr.s_addr = inet_addr(addr);
bzero(server_addr->sin_zero,8);
}
void set_file_path(char* filepath ,char* filename){ //先默认到./目录
strcpy(filepath,"./");
strcat(filepath,filename);
// strcat(filepath,"recv"); //test
}