每日一练(二十一)

12.6 通过函数修改查看文件属性

修改文件的访问属性

在这里插入图片描述

获取文件的属性

注意:

  • stat 与 lstat的主要区别在于作用与链接文件时,stat获取的是所链接文件的属性,lstat获取的是链接文件本身的属性
  • stat 与 fstat 一样,只不过是获取文件的方式不同,一种是文件路径,一种是文件描述符
  • 通过参数中的 struct stst *buf 结构体来获取文件的属性,结构体成员如下:

在这里插入图片描述

在这里插入图片描述

还可以通过系统定义的宏来判断文件类型、文件访问权限:

在这里插入图片描述

在这里插入图片描述

官方例子:

#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysmacros.h>

int
    main(int argc, char *argv[])
{
    struct stat sb;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if (lstat(argv[1], &sb) == -1) {
        perror("lstat");
        exit(EXIT_FAILURE);
    }

    printf("ID of containing device:  [%lx,%lx]\n",
           (long) major(sb.st_dev), (long) minor(sb.st_dev));

    printf("File type:                ");

    switch (sb.st_mode & S_IFMT) {
        case S_IFBLK:  printf("block device\n");            break;
        case S_IFCHR:  printf("character device\n");        break;
        case S_IFDIR:  printf("directory\n");               break;
        case S_IFIFO:  printf("FIFO/pipe\n");               break;
        case S_IFLNK:  printf("symlink\n");                 break;
        case S_IFREG:  printf("regular file\n");            break;
        case S_IFSOCK: printf("socket\n");                  break;
        default:       printf("unknown?\n");                break;
    }

    printf("I-node number:            %ld\n", (long) sb.st_ino);

    printf("Mode:                     %lo (octal)\n",
           (unsigned long) sb.st_mode);

    printf("Link count:               %ld\n", (long) sb.st_nlink);
    printf("Ownership:                UID=%ld   GID=%ld\n",
           (long) sb.st_uid, (long) sb.st_gid);

    printf("Preferred I/O block size: %ld bytes\n",
           (long) sb.st_blksize);
    printf("File size:                %lld bytes\n",
           (long long) sb.st_size);
    printf("Blocks allocated:         %lld\n",
           (long long) sb.st_blocks);

    printf("Last status change:       %s", ctime(&sb.st_ctime));
    printf("Last file access:         %s", ctime(&sb.st_atime));
    printf("Last file modification:   %s", ctime(&sb.st_mtime));

    exit(EXIT_SUCCESS);
}

12.7 常用进程产看方式

ps 静态查看系统进程快照

ps用来产看静态的进程统计信息,常用的选项如下:

  • a:显示当前终端下所有进程信息,包括其他用户的进程
  • u:以用户为主的格式输出进程信息
  • x:显示当前用户在所有终端下的进程
  • -e:显示系统内所有进程信息
  • -l:使用常格式显示进程信息
  • -f:使用完整格式显示进程信息

注意,有些命令选项是不加-的,所以经常将aux-elf分布组合使用

ps aux的执行结果如下:

image-20201207085559742

注意:

  • VSZ:占用虚拟内存(swap空间)的大小
  • RSS:占用常驻内存(物理内存)的大小
  • STAT:显示当前进程状态:S(休眠)、R(运行)、Z(僵死)、<(高优先级)、N(低优先级)、s(父进程)、+(前台进程)
  • TTY:表示该进程在哪个终端上运行,?表示未知或者不需要终端

top 动态查看进程信息

top用于动态查看进程的信息,默认三秒刷新一次,top执行结果如下:

image-20201207085920705

注意:

  • CPU信息:us,用户占用;sy,内核占用;ni,优先级调度占用;id,空闲CPU;wa,I/O等待占用;hi,硬件中断占用;si,软件中断占用;st,虚拟化占用。了解空闲的CPU百分比,主要看%id部分
  • 在top命令的全屏操作界面中,按P键根据CPU占用情况对进程列表进行排序,或按M键根据内存占用情况排序,按N键根据启动时间进行排序,按h键可以获得top程序的在线帮助信息,按q键可以正常地退出top程序
  • 可以在top操作界面通过k键来终止对应的进程

/proc 产看进程详细信息

Linux中/proc目录是一种文件系统,即proc文件系统,proc文件系统是一种伪文件系统(虚拟文件系统),存储的是当前内核运行状态的一些特殊文件。

所以用户可以通过查看/porc中的相关文件来获取系统硬件以及当前正在运行的进程的信息,其中有些文件虽然会返回进程相关的大量信息,但是实际大小却是0Byte,下面随便列出一个/proc下一个进程的目录:
image-20201207091659139

相关文件的说明参考链接:Linux /proc目录详解 - 滴水瓦 - 博客园 (cnblogs.com)

pstree 产看进程树

linux中,每一个进程都是由其父进程创建的。此命令以可视化方式显示进程,通过显示进程的树状图来展示进程间关系。如果指定了pid了,那么树的根是该pid,不然将会是init(pid: 1)

image-20201207090714124

htop 文本交互模式查看

htop与top很类似,但是htop是交互式的文本模式的进程查看器。它通过文字图形化地显示每一个进程的CPU和内存使用量、swap使用量。使用上下光标键选择进程,F7和F8改变优先级,F9杀死进程。Htop不是系统默认安装的,所以需要额外安装。

image-20201207091911426

12.8 fork 创建多个子进程

创建多个子进程

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, const char *argv[])
{
    int n;
    pid_t pid;
    for (i = 0; i < 5; i++) {
        pid = fork();
        if (pid < 0) {
          	perror("fork");  
        } else if (pid == 0) {  //进入子进程,直接返回,子进程不再fork子进程
            printf("this is %d process, pid:%d, ppid:%d\n", i, getpid(), getppid());
            exit(0);
        } else {
            wait(NULL);  //等待 i 儿子
        }
    }
    
    return 0;
}

12.9 反向递归遍历链表

给出一个单向不循环链表的头结点,要求不改变链表结构的情况下反向遍历链表中的元素。

思路:递归实现,判断p是否为空,来输出元素。

代码:

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

typedef int data_t;
typedef struct node {
    data_t data;
    struct node *next;
}node;

node *list_create();
int list_show(node *H);
node *list_pre_find(node *H, int post);
int list_insert_post(node *H, int post, data_t val);
int list_delete(node *H, int post);
int list_free(node *H);

int list_reverse_show(node *H);


int main(int argc, const char *argv[])
{
    int i, n, num;

    printf("input num size :");
    scanf("%d", &n); 

    node *H = list_create();
    printf("intput data:");
    for (i = 0; i < n; i++) {
        scanf("%d", &num);
        list_insert_post(H, i, num);
    }
    list_show(H);

    /* 功能测试 */
    list_delete(H, 0);
    list_show(H);
    list_insert_post(H, 0, 99);
    list_show(H);

    /* 递归反向遍历,不打印头结点数据,所以传入 H->next */
    list_reverse_show(H->next);
    puts("");

    list_free(H);
    return 0;
}

int list_reverse_show(node *H)
{
    node *p = H;
    if (p != NULL) {
        list_reverse_show(p->next);  //陷入递归,直到链表末尾开始返回,逐步执行printf
        printf("%d ", p->data);
    }

    return 0;
}

node *list_create()
{
    node *p = (node*)malloc(sizeof(node));
    if (NULL == p) {
        printf("malloc filed\n");
        return NULL;
    }

    memset(p, 0, sizeof(node));
    p->next = NULL;

    return p;
}

int list_show(node *H)
{
    if (NULL == H) {
        printf("H is NULL\n");
        return -1;
    }
    node *p = H;

    printf("H->");
    while (p->next != NULL) {
        p = p->next;
        printf("%d->", p->data);
        
    }
    printf("NULL\n");

    return 0;
}

node *list_pre_find(node *H, int post)
{
    if (NULL == H) {
        printf("H is NULL\n");
        return NULL;
    }
    int i;
    node *p;

    p = H;
    for (i = 0; i < post; i++) {
        if (NULL == p) {
            printf("post is over!\n");
            return NULL;
        }
        p = p->next;
    }

    return p;
}

int list_insert_post(node *H, int post, data_t val)
{
    if (NULL == H) {
        printf("H is NULL\n");
        return -1;
    }
    node *p, *q;

    p = list_create();
    p->data = val;

    q = list_pre_find(H, post);
    p->next = q->next;
    q->next = p;

    return 0;
}

int list_delete(node *H, int post)
{
    if (NULL == H) {
        printf("H is NULL\n");
        return -1;
    }
    node *p = list_pre_find(H, post);
    node *q;

    q = p->next;
    p->next = q->next;
    free(q);
    q = NULL;

    return 0;
}

int list_free(node *H)
{
    if (NULL == H) {
        printf("H is NULL\n");
        return -1;
    }

    node *p = H;
    node *q;

    while (p != NULL) {
        q = p;
        p = p->next;
        free(q);
    }
    q = NULL;

    return 0;
}

12.10 Linux 确定文件类型

Linux中确定文件类型使用命令file,使用方法为:

file filename

Linux中一切皆文件!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值