Linux 习题

习题来源于书籍和网络

1、编写一个孤儿进程,这个孤儿进程可以同时创建100个僵死进程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

int main(int arg, char* args[])
{
	pid_t pid = fork();
	if(pid == -1){
		return -1;
	}
	if(pid == 0)//子进程 
	{

		printf("my child\n");
		int i = 0;
		for(; i < 100; i++)
		{
			pid_t cpid = fork();
			if(cpid == -1)
			{
				printf("%s",strerror(errno));
			}
			if(cpid == 0)
			{
				printf("Grandson dead!\n");
				exit(0);
			}
		}
		pause();//因为子进程已死,所以要保留父进程才能看到僵死进程 
	}
	
	if(pid > 0)//父进程 
	{
		exit(0);
	}
	return 0;
}
2、两个程序a和b,b为a的子进程,在a程序中打开d.txt文件。在b中读取d.txt内容。
readProc.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int arg, char* args[])
{
	int fd = open("d.txt",O_RDONLY);
	
	pid_t pid = fork();
	if(pid < 0)
	{
		printf("%s\n",strerror(errno));
	}
	
	if(pid == 0)//创建子进程 
	{
		char sfd[10] = {0};
		sprintf(sfd,"%d",fd);
		char* const args_c[]={"writeProc",sfd,NULL};
		int err = execve("writeProc",args_c,NULL);//创建b进程,传入参数 文件描述符。 
		if(err == -1)
		{
			printf("%s",strerror(errno));
		}
	}
	return 0;
}

writeProc.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int arg, char* args[])
{
	if(arg < 2) return -1;
	
	char* buf[10] = {0};
	
	while(read(atoi(args[1]),buf,sizeof(buf)-1))
	{
		printf("%s",buf);
		memset(buf,0,sizeof(buf));
	}
	
	return 0;
}
3、子进程写数据父进程读取,无名管道的应用。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>

int main(int arg, char* args[])
{
	int fd[2];
	int *readfd = &fd[0];
	int *writefd = &fd[1];
	
	int rs = pipe(fd);
	int status;
	char buf[1024];
	char buf2[1024];
	if(rs < 0)
	{
		printf("%s",strerror(errno));
	}
	
	pid_t pid = fork();
	
	if(pid < 0)
	{
		printf("%s",strerror(errno));
	}
	
	if(pid == 0)
	{
		close(*readfd);//子进程关闭读 
		while(1)
		{
			memset(buf,0,sizeof(buf));
			read(0, buf, sizeof(buf));//从标准输入中读 
			write(*writefd,buf,strlen(buf));//写数据
		}
	}else if(pid > 0)
	{
		close(*writefd);//父进程关闭写 
		while(1)
		{
			int byte = read(*readfd,buf2,sizeof(buf2));
			if(byte > 0)
			{
				printf("%s\n",buf2);
				memset(buf2,0,sizeof(buf2));
			}	
		}
		wait(&status);
	}
	return 0;
}

4、有名管道读写。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>

int openfile(char* path, int *fd, int type)
{
	if(path == NULL || fd == NULL)
	{
		printf("pointer error!\n");
		return -1;
	} 
	if(type == 1){
		*fd = open(path,O_RDONLY);
		printf("read fd is %d \n", *fd);
	}else
	{
		*fd = open(path,O_WRONLY);
		printf("write fd is %d \n", *fd);
	}
	
	if(*fd < 0)
	{
		printf("openfile failed!\n");
		return -1;
	}
	return 0;	
}

int readfile(int *fd)
{
	char buf[100];
	int rs;
	
	while(1)
	{
		memset(buf,0,sizeof(buf));
		rs = read(*fd,buf,sizeof(buf));
		printf("%s",buf);
	}
	return 0;
}

int writefile(int *fd)
{
	char buf[100];
	while(1)
	{
		memset(buf,0,sizeof(buf));
		read(0,buf, sizeof(buf));
		write(*fd,buf,strlen(buf));
	}
	return 0;
}

int main(int arg, char* args[])
{
	if(arg < 3) return -1;
	int fd;
	int type = atoi(args[2]);
	openfile(args[1],&fd,type);
	if(fd < 0) return -1;
	
	if(type == 1)//只读 
	{
		readfile(&fd);
	}else{//只写 
		writefile(&fd);
	}
	close(fd);
	return 0;
}
5、共享内存读写。
创建共享内存
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main(int arg, char* args[])
{
	int shmid = shmget(IPC_PRIVATE, 1024, 0666);//分配共享内存 
	if(shmid < 0)
	{
		return -1;
	}
	printf("ipcs create success!\n");
	return 0;
}

读写共享内存
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <unistd.h>
int main(int arg, char* args[])
{
	char* shumbuf = shmat(atoi(args[1]),0,0);//挂载共享内存 

	if(atoi(args[2]) == 0)
	{
		scanf("%s",shumbuf);
	}else{
		printf("%s\n",shumbuf);
	}
	shmdt(shumbuf);
	return 0;
}

6、在linux下编写并使用一个库文件
头文件
#ifndef __LIB_UPPER_H__

#define __LIB_UPPER_H__

#include <stdio.h>
#include <string.h>

void upper(const char *src, char *desc);

#endif

源文件
#include "libupper.h" 

void upper(const char *src, char *desc)
{
	if(src == NULL || desc == NULL)
	{
		printf("NULL Pointer...");
		return;
	}
	
	int len = strlen(src);
	
	int i = 0;
	
	char tmp;
	for(; i < len; i++)
	{
		if(src[i] >= 'a' && src[i] <= 'z')
		{
			tmp = 'A' - 'a' + src[i];
		}else
		{
			tmp = src[i];
		}
		
		desc[i] = tmp;
	}
}

测试文件
#include <stdio.h>
#include <stdlib.h>
#include "libupper.h"

int main(int arg, char* args[])
{
	char dest[100] = {0};
	upper(args[1], dest);
	printf("%s\n",dest);
	return 0;
}

具体如何编译如何链接请参考 linux 操作记录 6.

7、程序 A 给 程序 B 发送信号,控制程序 B 在屏幕输出。
捕捉信号
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int isPrint = 0;

void catch_signal(int type)
{
	switch(type)
	{
		case SIGINT:
			printf("SIGINIT SIGNAL\n");
			isPrint ^= 1;
			break;
	}
}

int customSignal(int signo, void(*func)(int))//固定格式 
{
	struct sigaction act, oldact;
	act.sa_handler = func;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	return sigaction(signo, &act, &oldact);
}

int main(int arg, char* args[])
{
	printf("Kill Process type: %d %d\n",SIGSTOP,SIGKILL);
	customSignal(SIGINT, catch_signal);
	int count = 0;
	while(1)
	{
		if(isPrint)
		{
			printf("hello %d\n",count);
			sleep(1);
			count++;
		}
	}
	return 0;
}

发送信号
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>

int main(int arg, char* args[])
{
	if(arg < 1) return -1;
	
	int pid = atoi(args[1]);
	kill(pid, SIGINT);
	//int raise(int signal) == kill(getpid(), signal);
	//alarm(unsigned int seconds); 经过seconds秒发送 SIGALRM 信号 
	return 0;
}

8、写一个守护进程,其一秒中向一个本地日志里面写一些内容。
错误案例!!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>



/***

错误写法!! 

***/ 
void initDaemon()
{
	setsid();//提升为进程组长,脱离之前的控制终端 
	/*chdir("/");//改变工作目录,避免造成其它目录无法卸载 
	umask(0);//更改操作
	//关闭不必要的文件描述符 
	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);*/	
}

void writeLog(const struct tm* pm, char* buf)
{
	if(pm == NULL || buf == NULL)
	{
		printf("tm or buf is NULL...");
		return;
	}
	/*
	pm->tm_year + 1900;//年 
	pm->tm_mon + 1;//月 
	pm->tm_mday;//日 
	pm->tm_hour;//小时 
	pm->tm_min;//分钟 
	pm->tm_sec;//秒 
	*/
	memset((char*)buf, 0, sizeof(buf));
	
	sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", (pm->tm_year + 1900),(pm->tm_mon + 1),(pm->tm_mday),(pm->tm_hour),(pm->tm_min),(pm->tm_sec));
}

int main(int arg, char* args[])
{
	pid_t pid = fork();
	if(pid > 0) 
	{
		exit(0);
	}
	if(pid == 0)
	{
		printf("Child are created...");//printf 同时会打印到 mylog.txt中 为什么?
		
		initDaemon();
		
		FILE *f = fopen("mylog.txt","a");
		if(f == NULL)
		{
			printf("Open file failed!");
			return -1;
		}
		
		time_t t;
		struct tm *p = NULL;
		char buf[100];
		int count = 0;
		while(1)
		{
			printf("loop write %d...", count++);//printf 会打印到 mylog.txt中 为什么? 
			t = time(NULL);
			p = gmtime(&t);
			writeLog(p, buf);
			fwrite(buf,strlen(buf),1,f);//一直到缓冲区写满才会写入 
			sleep(1);
		}
		fclose(f);
	}
	return 0;
}

正确写法
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

void initDaemon()
{
	setsid();//提升为进程组长,脱离之前的控制终端 
	/*一下两步 chdir umask 涉及到权限问题,在读写文件时会造成麻烦,先去掉*/
	/*chdir("/");//改变工作目录,避免造成其它目录无法卸载 
	umask(0600);//更改操作*/	
	//关闭不必要的文件描述符 ,关闭后printf失效,不会再在屏幕输出 
	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);
}

void writeLog(const struct tm* pm, char* buf)
{
	if(pm == NULL || buf == NULL)
	{
		printf("tm or buf is NULL...\n");
		return;
	}
	/*
	pm->tm_year + 1900;//年 
	pm->tm_mon + 1;//月 
	pm->tm_mday;//日 
	pm->tm_hour;//小时 
	pm->tm_min;//分钟 
	pm->tm_sec;//秒 
	*/
	memset((char*)buf, 0, sizeof(buf));
	sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d\n", (pm->tm_year + 1900),(pm->tm_mon + 1),(pm->tm_mday),(pm->tm_hour),(pm->tm_min),(pm->tm_sec));
}

int main(int arg, char* args[])
{
	pid_t pid = fork();
	if(pid > 0) 
	{
		exit(0);
	}
	if(pid == 0)
	{
		printf("Child are created...\n");
		
		initDaemon();
		
		int fd = open("mylog.txt",O_APPEND | O_WRONLY);
		
		if(fd == -1)
		{
			printf("Open file failed! %s \n", strerror(errno));
			return -1;
		}
		
		printf("Open file Success! %d \n", fd);
		
		time_t t;
		struct tm *p = NULL;
		char buf[100];
		int count = 100;
		while(count > 0)
		{
			count--;
			//printf("loop write %d...\n", count++);
			t = time(NULL);
			p = gmtime(&t);
			writeLog(p, buf);
			printf("%s",buf);
			write(fd, buf, strlen(buf));
			sleep(1);
		}
		close(fd);
	}
	return 0;
}

9、编写一个程序,使用有名管道和多线程,让两个进程可以互相聊天。
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <sys/types.h>  
#include <errno.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include <pthread.h>


//pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//初始化了一个锁 

/**
传给多线程参数的结构 
**/
typedef struct ThreadArg
{
	int* fd;//文件描述符 
	char* path;//文件路径 
}TA;

/**
打开文件方式 
同一个程序 既要打开一个只读FIFO 也要打开一个只写FIFO
用于互相传输 
**/
int openFile(int * fd, const char* path, const char type)
{
	switch(type)
	{
		case 'r':
			*fd = open(path, O_RDONLY);
			break;
		case 'w':
			*fd = open(path, O_WRONLY);
			break;
		default:
			*fd = -1;
			break;
	}
	
	if(*fd == -1)
	{
		printf("Open File Error ! %s\n",strerror(errno));
		return -1;
	}
	printf("Open File Success ! %d\n", *fd);
	return 0;
}

/**
读文件 
**/
int readFile(int *fd)
{
	//pthread_mutex_lock(&mutex);//加锁 
	printf("Start read file ! %d\n", *fd);
	
	char buf[100] = {0};
	while(1)
	{
		while(read(*fd, buf, sizeof(buf)) > 0)//循环读入数据到buf中 
		{
			printf("%s",buf);//打印数据到屏幕 
			memset(buf,0,sizeof(buf));
		}
	}
	//pthread_mutex_unlock(&mutex);//解锁 
	return 0;
}

/**
写文件 
**/
int writeFile(int *fd)
{
	printf("Start write file ! %d\n", *fd);
	
	char buf[1024] = {0};//最多读入1024个字节 
	while(1)
	{
		//读取屏幕输入的字符串 不能读满,以免把'\0'给冲掉 
		read(STDIN_FILENO,buf, sizeof(buf) - 1);
		write(*fd, buf, strlen(buf));//注意这里是strlen,有多少读多少 
		memset(buf, 0, sizeof(buf));
	}
	return 0;
}

void* readThreadFunc(void* arg)
{
	TA* rt = arg;
	openFile(rt->fd,rt->path,'r');//第一个文件用来读 
	readFile(rt->fd);
	close(*(rt->fd));
	return NULL;
}

void* writeThreadFunc(void* arg)
{
	TA* wt = arg;
	openFile(wt->fd,wt->path,'w');//第二个文件用来写 
	writeFile(wt->fd);
	close(*(wt->fd));
	return NULL;
} 

int main(int arg, char* args[])
{
	if(arg < 3) return -1;
	
	int rfd, wfd; 
	TA rt, wt;
	
	rt.fd = &rfd;
	wt.fd = &wfd;
	
	rt.path = args[1];
	wt.path = args[2];
	
	pthread_t readThread, writeThread;
	
	//pthread_attr_t attr;
	//pthread_attr_init(&attr);	
	//pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//设置可分离线程 
	//pthread_create(&readThread, &attr, readThreadFunc, &rt);
	
	pthread_create(&readThread, NULL, readThreadFunc, &rt);
	pthread_create(&writeThread,NULL, writeThreadFunc, &wt);
	
	//pthread_attr_destroy(&attr);
	
	/*
	pthread_detach(readThread);//将此线程编程可分离线程 
	pthread_detach(writeThread);
	*/
	
	//等待子线程退出 
	pthread_join(readThread,NULL);
	pthread_join(writeThread,NULL);
	
	return 0;
}
10、TCP编写一个服务端和客户端,并可以实现服务端和客户端互相聊天
server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>

typedef struct sockaddr_in SOCKADDR;

typedef struct SOCK_THREAD
{
	int* client_sock;
	pthread_t* thread_cancel;
}SOCK_THREAD;

void* recvThread(void* arg)
{
	SOCK_THREAD sock_thread = *(SOCK_THREAD *)arg;
	char buf[1024];
	while(1)
	{
		memset(buf, 0, sizeof(buf));
		int retrecv = recv(*(sock_thread.client_sock), buf, sizeof(buf), 0);
		if(retrecv == -1)
		{
			printf("socket recv failed ! %s \n", strerror(errno));
			break;
		}
		else if(retrecv == 0)
		{
			printf("socket closed %s\n", strerror(errno));
			break;
		}
		else
		{
			printf("recv is %s", buf);
		}
	}
	pthread_cancel(*(sock_thread.thread_cancel));
	return NULL;
}

void* sendThread(void* arg)
{
	SOCK_THREAD sock_thread = *(SOCK_THREAD *)arg;
	char buf[1024];
	while(1)
	{
		memset(buf, 0, sizeof(buf));
		read(STDIN_FILENO, buf, sizeof(buf));
		if(send(*(sock_thread.client_sock), buf,strlen(buf),0) == -1)
		{
			printf("socket send failed ! %s \n", strerror(errno));
			break;
		} 
	}
	pthread_cancel(*(sock_thread.thread_cancel));
	return NULL;
}

int main(void)
{
	//1, create socket
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
	{
		printf("socket create failed ! %s \n", strerror(errno));
		return -1;
	}
	
	//参考操作记录 8 
	int opt = 1;
	if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(opt)) == -1)
	{
		printf("setsockopt failed ! %s \n", strerror(errno));
		return -1;
	}
	//2, bind
	SOCKADDR addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8080);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);	
	
	if(bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1)
	{
		printf("socket bind failed ! %s \n", strerror(errno));
		return -1;
	}
	
	//3, listen
	if(listen(sockfd, 20) == -1)
	{
		printf("socket listen failed ! %s \n", strerror(errno));
		return -1;
	}
	
	//4, accept
	while(1)
	{
		SOCKADDR cleint_addr;
		socklen_t client_socklen = sizeof(cleint_addr);
		int client_sockfd = accept(sockfd, (struct sockaddr*)&cleint_addr, &client_socklen);
		if(client_sockfd == -1)
		{
			printf("socket accept failed ! %s \n", strerror(errno));
			return -1;
		}
		printf("IP from %s \n", inet_ntoa(cleint_addr.sin_addr));
	
		//5, send/recv
		pthread_t recv_t, send_t;
		SOCK_THREAD sd_thread1, sd_thread2;
		sd_thread1.client_sock = &client_sockfd;
		sd_thread1.thread_cancel = &recv_t;
		sd_thread2.client_sock = &client_sockfd;
		sd_thread2.thread_cancel = &send_t;
		
		pthread_create(&recv_t, NULL, recvThread, &sd_thread1);
		pthread_detach(recv_t);
		pthread_create(&send_t, NULL, sendThread, &sd_thread2);
		pthread_detach(send_t);
		
		//此处不能join 否则线程会在此处挂起,无法接收下一个IP,造成只能一个client连接进来 
		/*pthread_join(recv_t, NULL);
		pthread_join(send_t, NULL);*/ 
	}
	
/*
	char buffr[1024];
	while(1)
	{
		memset(buffr, 0, sizeof(buffr));
		int retrecv = recv(client_sockfd, buffr, sizeof(buffr), 0);
		if(retrecv == -1)
		{
			printf("socket listen failed ! %s \n", strerror(errno));
			close(client_sockfd);
			return -1;
		}
		else if(retrecv == 0)
		{
			printf("socket closed %s\n", strerror(errno));
			close(client_sockfd);
			return 0;
		}
		else
		{
			printf("recv is %s \n", buffr);
			memset(buffr, 0, sizeof(buffr));
			read(STDIN_FILENO, buffr, sizeof(buffr));
			if(send(client_sockfd, buffr,strlen(buffr),0) == -1)
			{
				printf("socket send failed ! %s \n", strerror(errno));
				return -1;
			} 
		}
	}
*/
	close(sockfd);
	return 0;
}

client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>

typedef struct sockaddr_in SOCKADDR;

typedef struct SOCK_THREAD 
{
	int* client_sock;//sock描述符 
	pthread_t* thread_cancel;//需要退出的线程 
}SOCK_THREAD;

//接收消息线程 
void* recvThread(void* arg)
{
	SOCK_THREAD sock_thread = *(SOCK_THREAD *)arg;
	char buf[1024];
	while(1)
	{
		memset(buf, 0, sizeof(buf));
		int retrecv = recv(*(sock_thread.client_sock), buf, sizeof(buf), 0);
		if(retrecv == -1)
		{
			printf("socket listen failed ! %s \n", strerror(errno));
			break;
		}
		else if(retrecv == 0)//正常退出 
		{
			printf("socket closed %s\n", strerror(errno));
			break;
		}
		else
		{
			printf("recv is %s", buf);
		}
	}
	pthread_cancel(*(sock_thread.thread_cancel));
	return NULL;
}

void* sendThread(void* arg)
{
	SOCK_THREAD sock_thread = *(SOCK_THREAD *)arg;
	char buf[1024];
	while(1)
	{
		memset(buf, 0, sizeof(buf));
		read(STDIN_FILENO, buf, sizeof(buf));//read 会将线程挂起 虽然recvThread已经cancel 如果有join 它,还是会要输入read才能结束 
		if(send(*(sock_thread.client_sock), buf,strlen(buf),0) == -1)
		{
			printf("socket send failed ! %s \n", strerror(errno));
			break;
		} 
	}
	pthread_cancel(*(sock_thread.thread_cancel));
	return NULL;
}

int main(void)
{
	//1, create socket
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
	{
		printf("socket create failed ! %s \n", strerror(errno));
		return -1;
	}
	
	//2, connect
	SOCKADDR addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8080);
	addr.sin_addr.s_addr = inet_addr("192.168.0.254");
	
	if(connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1)
	{
		printf("socket connect failed ! %s \n", strerror(errno));
		return -1;
	}
	
	//3, send recv msg
	pthread_t recv_t, send_t;
	SOCK_THREAD sd_thread1, sd_thread2;
	sd_thread1.client_sock = &sockfd;
	sd_thread1.thread_cancel = &recv_t;
	sd_thread2.client_sock = &sockfd;
	sd_thread2.thread_cancel = &send_t;
	
	pthread_create(&recv_t, NULL, recvThread, &sd_thread1);
	pthread_create(&send_t, NULL, sendThread, &sd_thread2);
	
	pthread_join(recv_t, NULL);
//	pthread_join(send_t, NULL);//read会阻塞所以不能join 
/*	
	char buf[1024];
	while(1)
	{
		memset(buf, 0, sizeof(buf));
		read(STDIN_FILENO, buf, sizeof(buf));
		if(send(sockfd, buf,strlen(buf),0) == -1)
		{
			printf("socket send failed ! %s \n", strerror(errno));
			return -1;
		} 
		
		memset(buf, 0, sizeof(buf));
		int retrecv = recv(sockfd, buf, sizeof(buf), 0);
		if(retrecv == -1)
		{
			printf("socket listen failed ! %s \n", strerror(errno));
			close(sockfd);
			return -1;
		}
		else if(retrecv == 0)
		{
			printf("socket closed %s\n", strerror(errno));
		}
		else
		{
			printf("recv is %s \n", buf);
		}
	}
*/	
	close(sockfd);
	return 0;
}

makefile
.SUFFIXES:.c .o

CC=gcc
CFLAGS=-Wall -g
SRCS1=client.c
SRCS2=server.c
OBJS1=$(SRCS1:.c=.o)
OBJS2=$(SRCS2:.c=.o)
EXEC1=client
EXEC2=server

start:$(OBJS1) $(OBJS2)
	$(CC) -o $(EXEC1) $(OBJS1) -lpthread
	$(CC) -o $(EXEC2) $(OBJS2) -lpthread
	@echo "----Build Success----"
.c.o:
	$(CC) $(CFLAGS) -o $@ -c $<
clean:
	rm -f *.o
	-rm core.*
clexe:
	rm $(EXEC)

11、链接数据库,并可以执行查询语句
#include <stdio.h>
#include <stdlib.h>
#include <mysql/mysql.h>
#include <string.h>
#include <unistd.h>

int main(int argsc, char*argsv[])
{
	printf("MySql Connectting....\n");
	//----链接数据库----- 
	MYSQL mysql, *connection;
	
	//1, 初始化 
	mysql_init(&mysql);//mysql socket 初始化
	
	//2, 链接数据库 
	//连接到数据库,mysql_real_connect返回链接标识符 
	//connection 应该就是 mysql 的地址, 因为在下面的操作中两者可以替换 
	connection = mysql_real_connect(&mysql, "localhost","liju","123456","db1",0,0,0);
	
	//如果为空直接返回 
	if(connection == NULL)
	{
		printf("MySql Connect Error!! %s\n", mysql_error(&mysql));
		return EXIT_FAILURE;
	}else{
		printf("MySql Connectted!!\n");
	}
	
	//3,发送sql语句
	/*
	mysql_query() cannot be used for statements that contain binary data; 
	you must use mysql_real_query() instead. 
	(Binary data may contain the “\0” character, 
	which mysql_query() interprets as the end of the statement string.) 
	In addition, mysql_real_query() is faster than mysql_query() 
	because it does not call strlen() on the statement string.  
	
	//the last param means to query lenth, you can use it like this strlen(query)
	int mysql_real_query(MYSQL *mysql, const char *query, unsigned int length)
	
	mysql_query((MYSQL *mysql, const char *query)
	*/
	int ret = 0;
	ret = mysql_query(connection, "set names utf8");//先设置字符集,避免字符不匹配而查询不了。
	//成功返回 0  
	if(ret == 0)
	{
		printf("set names utf8 \n"); 
	}else{
		printf("set names utf8 failure!! %s\n", mysql_error(connection));
	}
	
	char promp[1024] = {0};
	sprintf(promp, "%s", "insert name>");
	write(STDOUT_FILENO, promp, strlen(promp));//如果是用 printf 会被 read 阻塞住,造成只有在 read 执行之后才打印
	
	char name[1024];
	memset(name, 0, sizeof(name));
	read(STDIN_FILENO, name, sizeof(name));
	name[strlen(name) - 1] = 0;//去掉回车
	
	//输入执行语句
	char sql[1024];
	memset(sql, 0, sizeof(sql));
	sprintf(sql, "select name from table1 where name = '%s'", name);
	
	printf("%s\n", sql);
	
	ret = mysql_query(connection, sql); 
	//成功返回 0  
	if(ret == 0)
	{
		printf("Search Success!!\n"); 
	}else{
		printf("Search failure!! %s\n", mysql_error(connection));
	}
	
	/*ret = mysql_query(connection, "select name from table1 where name = '季欣'"); 
	//成功返回 0  
	if(ret == 0)
	{
		printf("Search Success!!\n"); 
	}else{
		printf("Search failure!! %s\n", mysql_error(connection));
	}*/
	
	//4, 关闭数据库 
	//关闭链接标识符 
	mysql_close(connection);
	//-------------------
	return EXIT_SUCCESS;
}


12、用C语言编写一个程序,执行数据库语句,并且能打印结果到屏幕上,解决退格键显示^H 问题。
#include <stdio.h>
#include <stdlib.h>
#include <mysql/mysql.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <termios.h>

struct termios oldterm;
/*
tcgetattr用于获取终端的相关参数,成功返回零;失败返回非零;而tcsetattr函数用于设置终端参数,成功返回零;失败返回-1;
发生失败接口将设置errno错误标识。
返回的结果保存在termios结构体中,该结构体一般包括如下的成员:
tcflag_t c_iflag;      
tcflag_t c_oflag;      
tcflag_t c_cflag;      
tcflag_t c_lflag;     
cc_t     c_cc[NCCS];

VINTR 代表 ctrl+c 中断信号
term.c_cc[VINTR] = '\t'; 代表将tab设置成中断信号

具体请见博客内容
http://blog.csdn.net/kakaxi2222/article/details/45269627
*/
//ctrl+s 锁屏 ctrl+q 解锁屏
//用代码来控制退格键不回显
void setstty()
{
	struct termios term;
	if(tcgetattr(STDIN_FILENO, &term) == -1)//得到当前系统的 termios 设置
	{
		printf("tcgetattr error is %s \n", strerror(errno));
		return;
	}
	
	oldterm = term;//先保存之前的设置以供将来可以恢复设置
	
	term.c_cc[VERASE] = '\b';
	
	if(tcsetattr(STDIN_FILENO, TCSANOW, &term) == -1)
	{
		printf("tcsetattr error is %s \n", strerror(errno));
		return;
	}
}

//恢复系统的termios设置
void returnstty()
{
	if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &oldterm) == -1)//设置系统termion
	{
		printf("tcsetattr error is %s\n", strerror(errno));
	}
	return;
}

int main(int argsc, char*argsv[])
{
	//不回显退格建系统命令(当输入中文时有bug, 会多删除字符)
	//system("stty erase ^H");
	//不回显代码控制(当输入中文时有bug, 会多删除字符)
	setstty();

	printf("MySql Connectting....\n");
	//----链接数据库----- 
	MYSQL mysql, *connection;
	
	//1, 初始化 
	mysql_init(&mysql);//mysql socket 初始化
	
	//2, 链接数据库 
	//连接到数据库,mysql_real_connect返回链接标识符 
	//connection 应该就是 mysql 的地址, 因为在下面的操作中两者可以替换 
	connection = mysql_real_connect(&mysql, "localhost","liju","123456","db1",0,0,0);
	
	//如果为空直接返回 
	if(connection == NULL)
	{
		printf("MySql Connect Error!! %s\n", mysql_error(&mysql));
		return EXIT_FAILURE;
	}else{
		printf("MySql Connectted!!\n");
	}
	
	//3,发送sql语句
	/*
	mysql_query() cannot be used for statements that contain binary data; 
	you must use mysql_real_query() instead. 
	(Binary data may contain the “\0” character, 
	which mysql_query() interprets as the end of the statement string.) 
	In addition, mysql_real_query() is faster than mysql_query() 
	because it does not call strlen() on the statement string.  
	
	//the last param means to query lenth, you can use it like this strlen(query)
	int mysql_real_query(MYSQL *mysql, const char *query, unsigned int length)
	
	mysql_query((MYSQL *mysql, const char *query)
	*/
	int ret = 0;
	ret = mysql_query(connection, "set names utf8");//先设置字符集,避免字符不匹配而查询不了。
	//成功返回 0  
	if(ret == 0)
	{
		printf("set names utf8 \n"); 
	}else{
		printf("set names utf8 failure!! %s\n", mysql_error(connection));
	}
	
	char promp[1024] = {0};
	sprintf(promp, "%s", "insert name>");
	write(STDOUT_FILENO, promp, strlen(promp));//如果是用 printf 会被 read 阻塞住,造成只有在 read 执行之后才打印
	
	char name[1024];
	memset(name, 0, sizeof(name));
	read(STDIN_FILENO, name, sizeof(name));
	name[strlen(name) - 1] = 0;//去掉回车
	
	//输入执行语句
	char sql[1024];
	memset(sql, 0, sizeof(sql));
	//sprintf(sql, "select name from table1 where name = '%s'", name);
	sprintf(sql, "delete from table1 where name = '巫文超'");
	
	printf("%s\n", sql);
	
	ret = mysql_query(connection, sql); 
	//成功返回 0  
	if(ret == 0)
	{
		//%u mysql_affected_rows(connection)
		//mysql_store_result 返回查询结果 并保存到 result中
		MYSQL_RES *result = mysql_store_result(connection);
		if(result == NULL)
		{
			printf("resulst is null \n");
			return 0;
		}
		//记录列
		MYSQL_FIELD *field;
		//返回有多少字段(列)
		while((field = mysql_fetch_field(result)) != NULL)
		{
			printf("%s\t", field->name);
		}
		printf("\n");
		
		//记录行
		MYSQL_ROW row;
		int count = 0;
		while(1)
		{
			//提取每一条记录,返回行
			row = mysql_fetch_row(result);
			if(row == NULL) break;
			printf("%d ", count++);
		}
		//一定要用这个函数将result free掉
		mysql_free_result(result);
		printf("Search Success!!\n"); 
	}else{
		printf("Search failure!! %s\n", mysql_error(connection));
	}
	
	/*ret = mysql_query(connection, "select name from table1 where name = '季欣'"); 
	//成功返回 0  
	if(ret == 0)
	{
		printf("Search Success!!\n"); 
	}else{
		printf("Search failure!! %s\n", mysql_error(connection));
	}*/
	
	//4, 关闭数据库 
	//关闭链接标识符 
	mysql_close(connection);
	//-------------------
	returnstty();
	return EXIT_SUCCESS;
}


13、模仿 mysql client 编写一个 自己的mysql client
mydb.h
#ifndef MYDB_H
#define MYDB_H
#include <mysql/mysql.h>
#include <unistd.h>
#include <errno.h>
#include <termios.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

//初始化 mysql 对象 
int initMySQL(MYSQL* mysql);

//链接 mysql server 
int connectMySQL(MYSQL* mysql, const char* host, const char* userName, const char* password, const char* dbName); 

//生成sql语句
int sendAndResponseMySQL(MYSQL* mysql, const char* sql);

//关闭数据库链接
int closeMySQL(MYSQL* mysql); 
 
#endif

mydb.c
#include "mydb.h"

int initMySQL(MYSQL* mysql)
{
	if(mysql == NULL)
	{
		printf("MYSQL is NULL !\n");
		return -1;
	}
	
	mysql_init(mysql);
	
	return 0;
}

int connectMySQL(MYSQL* mysql, const char* host, const char* userName, const char* password, const char* dbName)
{
	if(mysql_real_connect(mysql, host, userName, password, dbName, 0, 0, 0) == NULL)
	{
		printf("%s\n", mysql_error(mysql));
		return EXIT_FAILURE;
	}
	
	return 0;
} 

int sendAndResponseMySQL(MYSQL* mysql, const char* sql)
{
	if(mysql == NULL)
	{
		printf("MYSQL is NULL !\n");
		return -1;
	}
	
	int ret = mysql_query(mysql, sql);
	
	if(ret != 0)
	{
		printf("%s\n", mysql_error(mysql));
		return -1;
	}
	
	MYSQL_RES *result = mysql_store_result(mysql);
	if(result == NULL)
	{
		printf("Query OK, %u rows affected\n", (unsigned int)mysql_affected_rows(mysql));
		return 0;
	}
	
	MYSQL_FIELD *field;
	int cols = 0;
	while((field = mysql_fetch_field(result)) != NULL)
	{
			printf("%s\t", field->name);
			cols++;
	}
	printf("\n");
	
	MYSQL_ROW row;
	
	while((row = mysql_fetch_row(result)) != NULL)
	{
		int i = 0;
		for(; i < cols; i++)
		{
			printf("%s\t", row[i]);
		}
		printf("\n");
	}
	
	printf("Query OK, %u rows affected\n", (unsigned int)mysql_affected_rows(mysql));
	mysql_free_result(result);
	return 0;
}

int closeMySQL(MYSQL* mysql)
{
	if(mysql == NULL)
	{
		printf("MYSQL is NULL !\n");
		return -1;
	}
	
	mysql_close(mysql);
	printf("Bye\n");
	return 0;
}

mysqlclient.c
#include "mydb.h"

int main(int argsc, char* argsv[])
{
	if(argsc != 4)
	{
		return EXIT_FAILURE;
	}
	
	if(strncmp(argsv[1], "-u", 2) != 0)
	{
		return EXIT_FAILURE;
	}
	
	if(strncmp(argsv[3], "-p", 2) != 0)
	{
		return EXIT_FAILURE;
	}
	
	const char* password = getpass("Please input password:");
	write(STDOUT_FILENO, "Please input DB name:", strlen("Please input DB name:"));
	char dbName[100] = {0};
	read(STDIN_FILENO, dbName, sizeof(dbName));
	dbName[strlen(dbName) - 1] = 0;
	
	system("stty erase ^H");
	
	MYSQL mysql;
	
	initMySQL(&mysql);
	if(connectMySQL(&mysql, "localhost", argsv[2], password, dbName) !=0 )
	{
		return EXIT_FAILURE;
	}
	
	char sql[1024];
	while(1)
	{
		write(STDOUT_FILENO, "mysql> ", strlen("mysql> "));
		
		memset(sql, 0, sizeof(sql));
		read(STDIN_FILENO, sql, sizeof(sql));
		sql[strlen(sql) - 1] = 0;
		
		if(strncmp(sql, "quit", 4) == 0)
		{
			break;
		}
		
		sendAndResponseMySQL(&mysql, sql);
	}

	closeMySQL(&mysql);
	return EXIT_SUCCESS;
}

14、用epoll来处理大并发问题。(模板)
/**
epoll 有两种模式 ET(高速工作方式 只支持noblok socket) LT 

ET:: edge-trigger 模式下只有某个 fd 从 unreadable 变为 readable
 或从 unwritable 变为 writable 时,epoll_wait 才会返回该 fd。也就是说
 如果一个fd的状态在没有改变的情况下,如果来了同样是事件,那么ET 就不会处理这个事件?? 

LT:: LT 模式是缺省模式,当epoll正在处理消息时, 又来了一个消息,
则下一次循环时,会立即返回这个消息,以供处理。LT 不会丢失消息。
只要buffer有数据,就不断的通知。 level-trigger 模式下只要某个 fd 处于 
readable/writable 状态,无论什么时候进行 epoll_wait 都会返回该 fd

epoll 模型适用于 数量较多 但是 数据量较少的连接,因为它要不断的轮询。 

多线程 模型适用于 数量较少 但是 数据量较大的情况。 


**/


#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h> 
#include <sys/types.h> 
#include <string.h>  
#include <errno.h>  
#include <sys/epoll.h>
#include <fcntl.h>
#include <unistd.h>
#include <arpa/inet.h>  
#include <netinet/in.h>  

#define EPOLL_NUMS 100

typedef struct sockaddr_in SOCKADDR;

int acceptThread(int fd)
{
	SOCKADDR cleint_addr;  
    socklen_t client_socklen = sizeof(cleint_addr);  
    int client_sockfd = accept(fd, (struct sockaddr*)&cleint_addr, &client_socklen);  
    if(client_sockfd == -1)  
    {  
        printf("socket accept failed ! %s \n", strerror(errno));   
    }
	return client_sockfd;  
}

//接收消息  
int recvThread(int fd)  
{  
    char buf[1024]; 
	int ret = 0; 
    while(1)  
    {  
        memset(buf, 0, sizeof(buf));  
        int retrecv = recv(fd, buf, sizeof(buf), 0);  
        if(retrecv == -1)  
        {  
            printf("socket listen failed ! %s \n", strerror(errno));  
            ret = - 1;
            break;  
        }  
        else if(retrecv == 0)//正常退出   
        {  
            printf("socket closed %s\n", strerror(errno));  
            ret = -1;
            break;  
        }  
        else  
        {  
            printf("recv is %s", buf);  
        }  
    }  
    return ret;  
}  

//发送消息 
int sendThread(int fd)  
{  
    char buf[1024];  
    int ret = -1;
    while(1)  
    {  
        memset(buf, 0, sizeof(buf));  
        read(STDIN_FILENO, buf, sizeof(buf));//read 会将线程挂起 虽然recvThread已经cancel 如果有join 它,还是会要输入read才能结束   
        if(send(fd, buf,strlen(buf),0) == -1)  
        {  
            printf("socket send failed ! %s \n", strerror(errno));  
            ret = -1;
            break;  
        }   
    }  
    return ret;  
} 

//创建非阻塞
 void setnonblocking(int fd)
 {
 	int opts = fcntl(fd, F_GETFL);
 	if(opts < 0)
 	{
 		printf("fcntl failed %s\n", strerror(errno));
	}
	
	opts = opts | O_NONBLOCK;
	if(fcntl(fd, F_SETFL, opts) < 0)
	{
		printf("fcntl failed %s\n", strerror(errno));
	}
 }

//先创建服务端的socket 
int socket_create()
{
	//1,创建SOCKET 
	int sockfd  = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
	{
		printf("socket create failed ! %s \n", strerror(errno));  
        return -1;
	}
	
	//2, 断开再连接无需等待,具体查看博客 操作记录 8 
	int opt = 1;  
    if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1)  
    {  
        printf("setsockopt failed ! %s \n", strerror(errno));  
        return -1;  
    } 
    
    //3, 绑定端口和IP
	SOCKADDR addr;  
    addr.sin_family = AF_INET;  
    addr.sin_port = htons(8080);  
    addr.sin_addr.s_addr = htonl(INADDR_ANY);     
      
    if(bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1)  
    {  
        printf("socket bind failed ! %s \n", strerror(errno));  
        return -1;  
    }   
    
    //4, 开始侦听
	if(listen(sockfd, 20) == -1)
	{
		printf("socket listen failed ! %s \n", strerror(errno));  
        return -1;
	}
	
	return sockfd; 
}

int main(void)
{
	//1、获得服务端的 socket 描述符 
	int sockfd = socket_create();
	
	//2、设置为非阻塞 
	setnonblocking(sockfd);
	
	//3、声明一个 epll_event 结构,用来放入 epoll 池中,每次轮询都会从池中加入有变化的 描述符 
	struct epoll_event ev, events[EPOLL_NUMS];
	
	//4、创建epoll的描述符 数量和池的数量一样大, 表示对多能放多少文件描述符 
	int epfd = epoll_create(EPOLL_NUMS);
	
	//5、把服务端 fd 加到epoll池中 
	ev.data.fd = sockfd;
	ev.events = EPOLLIN | EPOLLERR | EPOLLHUP ;//| EPOLLET;
	 
	//用来添加、修改、删除需要侦听的文件描述符及其事件 
	//每次添加、修改、删除文件描述符都要用到epoll_ctr,所以
	//要尽量少的调用epoll_ctl.
	//EPOLL_CTL_ADD 添加fd到 epfd中 
	//EPOLL_CTL_MOD 修改指定的fd 
	//EPOLL_CTL_DEL 从epfd中删除一个fd    
	epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);
	
		
	int st = -1;
	//6、开始轮询 
	while(1)
	{
		//返回有事件的描述符的总数量 
		int fd_num = epoll_wait(epfd, events, EPOLL_NUMS, -1);
		//错误返回-1 
		if(fd_num == -1)
		{
			printf("%s\n", strerror(errno));
			break;
		}
		
		//遍历每个有事件的描述符, 这时 events 里面存的只有来事件的描述符 
		int i;
		for( i = 0; i < fd_num; i++)
		{
			if(events[i].data.fd < 0)
			{
				continue;
			}
			//假如是服务端的描述符则执行accept, 并且将客户端的 描述符 添加到池中 
			if(events[i].data.fd == sockfd)
			{
				st = acceptThread(sockfd);
				if(st >= 0)
				{
					ev.data.fd = st;
					ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;
					epoll_ctl(epfd, EPOLL_CTL_ADD, st, &ev);
					continue;
				}
			}
			
			//如果来的是输入事件,则执行socket_recv 
			if(events[i].events & EPOLLIN)
			{
				st = events[i].data.fd;
				if(recvThread(st) <= 0)
				{
					close(st);
					events[i].data.fd = -1;
				}
			}
			//如果是错误事件,则执行 close 
			if(events[i].events & EPOLLERR)
			{
				close(st);
				events[i].data.fd = -1;
			}
			//如果是挂起事件, 则执行close 
			if(events[i].events & EPOLLHUP)
			{
				close(st);
				events[i].data.fd = -1;
			}
		}
		//7、循环结束关闭epoll ,epoll 描述符用完后需要用close关闭 
		close(epfd);
		return 0;
	} 
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux习题综合练习及答案仅选择题 1、Linux的第二块硬盘的第一个分区应该表示为:() A.  /hda1              B.  /hdb1             C.   /hdba             D.  /hda2 2、在Linux中有关IDE设备命名编号正确的有(      ) A. sda   第一个 IDE 控制器,主设备         B. sdb   第二个 IDE 控制器,次设备C.  hda   第二个 IDE 控制器,主设备           D. hda   第一个 IDE 控制器,主设备 3、利用命令find查找当前目录下的名称尾为.c的文件,并将结果输出到标准输出的命令是(      ) A. find . -name "?.c" –print         B. find . -name "#.c" –print C. find . -name "!*.c" –print        D. find . -name "*.c" –print 4、启动运行级别3代表什么:() A.  关闭系统                                                 B.  单用户管理模式 C.  无网络功能的多用户模式             D.  带有网络功能的多用户模式 5、为了将当前目录下的归档文件myftp.tgz解压缩到/tmp目录下,我们可以使用(      ) A. tar xvzf myftp.tgz -C /tmp        B. tar xvzf myftp.tgz -R /tmp C. tar vzf myftp.tgz -X /tmp         D. tar xvzf myftp.tgz /tmp 6、怎样新建一个新文件:() A. mk hello.c             B. rm hello.c  C. touch hello.c   D. new hello.c 7、下面哪些命令可以分页显示大文本文件:(    ) A.  more                     B.  cat C.  type                      D.  less 8、  ls –al 命令列出下面的文件列表,问那一行代表是链接文件。() A. -rw-------  2 hel-s  users   56  sep 09 11:05  hello B. -rw-------  2 hel-s  users   56  sep 09 11:05  goodbey C. drwx-----  1 hel   users  1024  sep 10 08:10  zhang D. lrwx-----  1 hel  users  2024    sep 12 08:12   cheng       9、以下哪几种是vi的工作模式(      )(多选) A. 命令模式         B. 删除模式        C. 编辑模式      D. 末行模式 10、临时注销一个用户,可以直接修改/etc/shadow文件,即在该用户口令前加(      ) A. !            B.#                C.%                D.* 11、启动X-Windows命令是(      ) A. Start          B.startx           C. begin           D. beginx 12、安装Linux系统对磁盘分区的要求是( ) A 至少有一个磁盘分区 B 至少有两个磁盘分区 C 至少有三个磁盘分区 D 至少有四个磁盘分区 13、下面哪个文件包含了主机名到ip地址的映射关系() A. /etc/hostname               B. /etc/hosts C. /etc/resolv.conf              D. /etc/networks 14、在Linux系统,默认的shell是什么:() A.  bash               B. ash C.   csh                D. gnush 15、Pwd命令的功能是() A 设置用户的口令 B 显示用户的口令 C 相当于Windows命令行里输入C D命令 D 相当于在windows命令行里输入dir命令 16、当一个目录作为一个挂载点被使用后,该目录上的原文件( ) A、 被永久删除 B、被隐藏,待挂载设备卸载后恢复 C、 被放入回收站 D、被隐藏,待计算机重新启动后恢复 17、执行命令“chmod o+rw myfile”后,myfile文件的权限变化为( ) A、 同组用户可读写myfile文件         B、其他用户可读写myfile文件 C、 所有用户都可读写myfile文件      D、文件所有者读写myfile文件 18、tar命令可以进行文件的( ) A、压缩、归档和解压缩 B、压缩和解压缩 C、压缩和归档 D、归档和解压缩 19、负责执行防火墙规则的服务(守护进程)是( ) A、 iptables B、network C、security D、xinetd 20、使用vi编辑文本只读时,保存并退出的命令是?(单选题) A :w!        B :q!       C   :wq       D   :e! 21、当一个文件属性为drwxrwxrwt,则这个文件的权限是什么样的?(多选题) A: 任何用户皆可读取、可写入         B: root 可以删除该目录的文件 C: 给普通用户以文件所有者的特权     D:文件拥有者有权删除该目录的文件 22、什么命令用来查看硬盘被占用了多少空间和剩余多少空间? (单选题) A : du   B: df    C: free   D: vmstat 23、Linux 使用者的帐号、密码与群组的名称文件放在哪些文件里?(多选题) A: /etc/passwd                  B:   /etc/shadow C: /etc/group                     D:   /etc/users 24、暂停某用户帐号可以使用如下哪些方法?(多选题) A.把/etc/passwd文件中该用户信息字段前加# B.passwd -1[用户名] C.将/etc/passwd该用户信息shell字段改成/sbin/nologin D.passwd -u[用户名] 。。。。。。。。。。。。。。。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值