系统编程练习

  • 传递一个路径名,还有一个文件名,搜索对应路径下是否有该文件,有就打印显示该文件的绝对路径。
#include 
#include 
#include 
#include 
#include 

void search_file_in_dir(const char *dir_path, const char *file_name);

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s [dir] [file]\n", argv[0]);
        return -1;
    }
    search_file_in_dir(argv[1], argv[2]);
    return 0;
}

void search_file_in_dir(const char *dir_path, const char *file_name) {
    DIR *dir = opendir(dir_path);
    if (dir == NULL) {
        perror("opendir");
        return;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        char file_path[1024];
        snprintf(file_path, sizeof(file_path), "%s/%s", dir_path, entry->d_name);
        struct stat st;
        if (stat(file_path, &st) == -1) {
            perror("stat");
            continue;
        }

        if (S_ISDIR(st.st_mode)) {  // 如果是目录,则递归搜索
            search_file_in_dir(file_path, file_name);
        } else if (S_ISREG(st.st_mode)) {  // 如果是普通文件,则判断文件名是否匹配
            if (strcmp(entry->d_name, file_name) == 0) {
                printf("%s/%s\n", dir_path, file_name);
            }
        }
    }

    closedir(dir);
}
  • 传递任意一个目录路径,能够显示该目录的ls -l的效果。
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

void print_file_info(const char *path, const struct stat *file_stat)
{
    // 文件类型和访问权限
    printf("%c", S_ISDIR(file_stat->st_mode) ? 'd' : '-');
    printf("%c", file_stat->st_mode & S_IRUSR ? 'r' : '-');
    printf("%c", file_stat->st_mode & S_IWUSR ? 'w' : '-');
    printf("%c", file_stat->st_mode & S_IXUSR ? 'x' : '-');
    printf("%c", file_stat->st_mode & S_IRGRP ? 'r' : '-');
    printf("%c", file_stat->st_mode & S_IWGRP ? 'w' : '-');
    printf("%c", file_stat->st_mode & S_IXGRP ? 'x' : '-');
    printf("%c", file_stat->st_mode & S_IROTH ? 'r' : '-');
    printf("%c", file_stat->st_mode & S_IWOTH ? 'w' : '-');
    printf("%c", file_stat->st_mode & S_IXOTH ? 'x' : '-');

    // 硬链接数、所有者、组、大小
    printf(" %2ld ", file_stat->st_nlink);
    struct passwd *pw = getpwuid(file_stat->st_uid);
    printf("%-8s ", pw ? pw->pw_name : "unknown");
    struct group *gr = getgrgid(file_stat->st_gid);
    printf("%-8s ", gr ? gr->gr_name : "unknown");
    printf("%10ld ", file_stat->st_size);

    // 时间
    char time_buf[32];
    strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M", localtime(&file_stat->st_mtime));
    printf("%s ", time_buf);

    // 文件名
    printf("%s\n", path);
}

int main(int argc, char *argv[])
{
    if (argc != 2) {
        fprintf(stderr, "Usage: %s \n", argv[0]);
        return 1;
    }
    DIR *dir = opendir(argv[1]);
    if (!dir) {
        perror("opendir");
        return 1;
    }
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        char path[1024];
        snprintf(path, sizeof(path), "%s/%s", argv[1], entry->d_name);
        struct stat file_stat;
        if (lstat(path, &file_stat) == -1) {
            perror("lstat");
            continue;
        }
        print_file_info(entry->d_name, &file_stat);
    }
    closedir(dir);
    return 0;
}

  • 打印当前目录,然后改变当前目录,再打印当前目录。
#include 
#include 

int main() {
    char cwd[1024];
    if (getcwd(cwd, sizeof(cwd)) != NULL) {
        printf("Current working directory: %s\n", cwd);
    } else {
        perror("getcwd() error");
        return 1;
    }

    if (chdir("/path/to/new/directory") == -1) {
        perror("chdir() error");
        return 1;
    }

    if (getcwd(cwd, sizeof(cwd)) != NULL) {
        printf("New working directory: %s\n", cwd);
    } else {
        perror("getcwd() error");
        return 1;
    }

    return 0;
}

  • 写个C语言程序 创建一个目录,然后删除掉它。
#include 
#include 
#include 
#include 
#include 

int main() {
    // 创建一个名为 "example_directory" 的目录
    if(mkdir("example_directory", 0777) == -1) {
        perror("mkdir error");
        exit(EXIT_FAILURE);
    }

    printf("Created directory successfully!\n");

    // 删除刚才创建的目录
    if(rmdir("example_directory") == -1) {
        perror("rmdir error");
        exit(EXIT_FAILURE);
    }

    printf("Deleted directory successfully!\n");

    return EXIT_SUCCESS;
}

  • 实现tree
#include 
#include 
#include 
#include 

void print_tree(char *path, int depth) {
    DIR *dir;
    struct dirent *entry;
    char new_path[1024];

    if (!(dir = opendir(path))) {
        perror("opendir error");
        exit(EXIT_FAILURE);
    }

    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR) {
            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
                continue;
            }
            printf("%*s%s/\n", depth*4, "", entry->d_name);
            sprintf(new_path, "%s/%s", path, entry->d_name);
            print_tree(new_path, depth+1);
        } else {
            printf("%*s%s\n", depth*4, "", entry->d_name);
        }
    }

    closedir(dir);
}

int main(int argc, char *argv[]) {
    char *path;

    if (argc < 2) {
        path = ".";
    } else {
        path = argv[1];
    }

    print_tree(path, 0);

    return 0;
}

共享内存是进程间通信的一种方法,常用到的有mmap和shm,下面做一个比较。

mmap机制:

在磁盘上建立一个文件,然后把文件内容映射到虚拟内存上,在每个进程的虚拟存储器里面,单独开辟一个空间来进行映射。在多进程情况下,不会对实际的物理存储器(主存)消耗太大。
即将一个文件或者其它对象映射到进程的虚拟地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一 一对映关系。
实现这样的映射关系后,进程就可以采用指针的方式操作这一段内存,而系统会自动回写到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享,也就是不再局限于具有亲缘关系的进程间通信。
简而言之,就是在进程虚拟空间上添加一个段,并将其与物理磁盘地址相连(映射),而在创建虚拟段的时候,并没有将任何文件数据拷贝至物理内存。

shm机制

多个进程的地址空间都映射到同一块物理内存,这样多个进程都能看到这块物理内存,实现进程间通信,而且不需要数据的拷贝,所以速度最快。当系统断电后,其中的文件会全部自行销毁,这点与mmap不同。

对比:
1、mmap是在磁盘上建立一个文件,每个进程地址空间中开辟出一块空间进行映射。而对于shm而言,shm每个进程最终会映射到同一块物理内存。shm保存在物理内存,这样读写的速度要比磁盘要快,但是存储量不是特别大。

2、mmap:磁盘->进程,shm:进程->内存(断电清除)。共享内存shm是在内存中创建空间,然后每个进程映射到此处;内存映射mmap是在磁盘中创建一个文件,然后每个进程映射到此处;

3 当机器重启时,mmap把文件保存在磁盘上,所以不会丢失,而共享内存shm存储在内存上就会丢失;

你可能感兴趣的:(linux,后端,c++,c语言,linux)