系统编程
命令行解析
GETOPT 函数
头文件 : <unistd.h>
原型 : int getopt(int argc, char * const argv[], const char *optstring);
argc argv : 由main 函数的参数直接传递而来
optstring : 一个包含准确选项的字符串
返回值 : 返回下一个选项
// 四个全局变量 通常和while一起使用
//char *optarg 指向当前选项的参数
//int optind 下一个选项的索引
//int optopt 最后一个已知选项
//int opterr 向stderr打印错误
man 3 getopt
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "ab:c::")) != -1) {
switch (opt) {
case 'a' :
printf("opt a found\n");
printf("ind = %d\n", optind);
break;
case 'b' :
printf("opt b found\n");
printf("ind = %d\n", optind);
printf("arg for b = %s\n", optarg);
break;
case 'c' :
printf("opt c found\n");break;
default :
fprintf(stderr, "Usage : %s -a -b arg -c[carg]", argv[0]);
exit(1);
}
}
return 0;
}
文件与目录基本操作
open
多个进程打开同一个文件, 内核只会维护一个父本,每个进程进行写的时候在用户空间有缓冲,按下保存后才写入,并且后面写入的会覆盖前面的。
用户只能通过系统调用来进入内核(相当于要办事先填表) 填好表之后调用open()下沉到内核(内核也有缓冲机制)进行等待IO,等待cpu调度。
返回一个文件描述符 进程对文件进行标号(每个进程有个表记录自己的标号)
用户态下沉到内核态 内核态打开文件返回到用户态
系统调用 内核实现的时候也是有缓冲的(在open中 O_DIRECT 这个可以最小化缓冲称为直接IO )
man open //具体查看man
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode); //加了权限的
//第一个参数是文件名
//第二个参数是个位掩码 O_RDONLY, O_WRONLY, or O_RDWR.
void perror(const char *s); //int errno; 有个全局变量 当出错了旧设置他多以perror要放在判断里面
int main(int argc, char **argv) {
int fd;
if ((fd = open(argv[1], O_RDONLY)) < 0) {
fprintf(stderr, "ERROR!\n");
perror("open");
}
perror("open2"); // 如果出错errno已经被设置了
}
int close(int fd); //内核有个计数器 当为0时释放内存
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
// 实现cp功能 用系统调用实现
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[]) {
int fd, fd2;
if (argc != 3) {
fprintf(stderr, "Usage : %s faild", argv[0]);
}
if ((fd = open(argv[1], O_RDONLY)) < 0) {
perror("open");
exit(1);
}
if ((fd2 = open(argv[2], O_CREAT | O_RDWR, 0666)) < 0) { //要给权限不然全是零
perror("open"); //umask会对other进行减法操作
exit(1);
}
while (1) {
char buff[512] = {0};
ssize_t size = read(fd, buff, sizeof(buff));
printf("%s", buff);
write(fd2, buff, size); //读到多少就写多少
if (size <= 0) {
break;
}
}
close(fd);
close(fd2);
return 0;
}
fopen() 标准io提供的一系列函数
FILE *fopen(const char *pathname, const char *mode);
//打开一个文件流
int fseek(FILE *stream, long offset, int whence);
//在文件流里寻找 whence 可以设置SEEK_SET,SEEK_CUR, or SEEK_END
//实现cp功能 ./a.out -r 1.c -w 2.c 用标准IO实现
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int opt;
char rfile[50] = {0}, wfile[20] = {0};
FILE *r, *w;
while ((opt = getopt(argc, argv, "r:w:")) != -1) {
switch(opt) {
case 'r':
strcpy(rfile, optarg);
break;
case 'w':
strcpy(wfile, optarg);
break;
default:
fprintf(stderr, "Usage : %s -r -w\n", argv[0]);
exit(1);
}
}
if ((strlen(rfile) == 0) || strlen(wfile) == 0) {
fprintf(stderr, "Usage : %s -r -w \n", argv[0]);
exit(1);
}
if ((r = fopen(rfile, "r")) == NULL) {
perror(rfile);
exit(1);
}
if ((w = fopen(wfile, "w")) == NULL) {
perror(wfile);
exit(1);
}
while (1) {
char buff[512] = {0};
size_t size = fread(buff, 1, sizeof(buff), r);
if (size <= 0) {
break;
}
fwrite(buff, 1, size, w);
}
fclose(r);
fclose(w);
return 0;
}
目录操作
#include <dirent.h>
DIR *opendir(const char *name);
struct dirent *readdir(DIR *dirp);
int chdir(const char *path);
struct dirent {
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[256];
};
实现ls
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
int main(int argc, char **argv) {
DIR *dir = NULL;
char dir_name[256] = {0};
if (argc == 1) {
strcpy(dir_name, ".");
} else {
strcpy(dir_name, argv[1]);
}
if ((dir = opendir(dir_name)) == NULL) {
perror(dir_name);
exit(1);
}
while (1) {
struct dirent *dir_ptr;
if((dir_ptr = readdir(dir)) == NULL) {
break;
}
printf("%s\n", dir_ptr->d_name);
}
closedir(dir);
return 0;
}
// 还有一些命令来完善ls
//stat 查看文件具体信息
int stat(const char *pathname, struct stat *statbuf);
struct stat {
dev_t st_dev;
ino_t st_ino;
mode_t st_mode; //stat.h文件里
nlink_t st_nlink;
uid_t st_uid; // getpwuid
gid_t st_gid; // getgrgid
dev_t st_rdev;
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
};