实验三、进程管理

1、创建并运行内核线程

kthread.c:

#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/delay.h>
​
MODULE_LICENSE("GPL");
​
#define BUF_SIZE 20
​
static struct task_struct *myThread = NULL;
​
static int print(void *data)
{
    while(!kthread_should_stop()){//接收kthread_stop传递的结束线程信号,如果内核线程中未用此函数,则kthread_stop使其结束。
        printk("New kthread is running.");
        msleep(2000);
    }
    return 0;
}
​
static int __init kthread_init(void)
{
    printk("Create kernel thread!\n");
    myThread = kthread_run(print, NULL, "new_kthread");//创建并启动一个线程
    return 0;
}
​
static void __exit kthread_exit(void)
{
    printk("Kill new kthread.\n");
    if(myThread)
        kthread_stop(myThread);//发送信号给myThread指向的线程,使之退出
}
​
module_init(kthread_init);
module_exit(kthread_exit);

编译运行:

分析运行结果,加载模块后,执行 kthread_run(print, NULL, "new_kthread"),成功创建并启动了内核线程,然后一直在运行,当卸载掉该模块后,调用 kthread_stop(myThread),退出线程。

2、打印输出当前系统 CPU 负载情况

cpu_loadavg.c:

#include <linux/module.h>
#include <linux/fs.h>
​
MODULE_LICENSE("GPL");
​
char tmp_cpu_load[5] = {'\0'};
​
static int get_loadavg(void)
{
    struct file *fp_cpu;
    loff_t pos = 0;
    char buf_cpu[10];
    fp_cpu = filp_open("/proc/loadavg", O_RDONLY, 0);
    if (IS_ERR(fp_cpu)){
        printk("Failed to open loadavg file!\n");
        return -1;
    }
    kernel_read(fp_cpu, buf_cpu, sizeof(buf_cpu), &pos);
    strncpy(tmp_cpu_load, buf_cpu, 4);
    filp_close(fp_cpu, NULL);
    return 0;
}
​
static int __init cpu_loadavg_init(void)
{
    printk("Start cpu_loadavg!\n");
    if(0 != get_loadavg()){
        printk("Failed to read loadarvg file!\n");
        return -1;
    }
    printk("The cpu loadavg in one minute is: %s\n", tmp_cpu_load);
    return 0;
}
​
static void __exit cpu_loadavg_exit(void)
{
    printk("Exit cpu_loadavg!\n");
}
​
module_init(cpu_loadavg_init);
module_exit(cpu_loadavg_exit); 

编译运行:

 

3、打印输出当前处于运行状态的进程的 PID 和名字

process_info.c:

#include <linux/module.h>
#include <linux/sched/signal.h>
#include <linux/sched.h>
​
MODULE_LICENSE("GPL");
​
struct task_struct *p;
​
static int __init process_info_init(void)
{
    printk("Start process_info!\n");
    for_each_process(p){
        if(p->state == 0)
            printk("1)name:%s  2)pid:%d  3)state:%ld\n", p->comm, p->pid, p->state);
    }
    return 0;
}
​
static void __exit process_info_exit(void)
{
    printk("Exit process_info!\n");
}
​
module_init(process_info_init);
module_exit(process_info_exit); 

编译运行:

成功打印出了当前运行态的:

  • 进程名:insmod

  • 进程ID:7166

  • 状态:0

4、使用 cgroup 实现限制 CPU 核数

1、挂载tmpfs格式的cgroup文件夹

2、挂载cpuset管理子系统

3、设置cpu核数(设置0号内存结点,只使用cpu的0、1、2核。)

4、while_long.c:(实现死循环,持续运行,最后使用快捷键Ctrl+z结束)

#include <stdio.h>
#include <stdlib.h>
​
int main(int argc, char *argv[])
{
    while (1){}
    printf("Over");
    exit(0);
}

5、验证

(1)编译上面的c程序,指定在cpuset子系统的mycpuset控制组中运行while_long。

首先安装cgroup:

yum install libcgroup

(2)使用top命令得到while_long的进程id为7899:

5、使用 cgroup 实现不允许访问U盘

在该实验中,需要注意U盘接口类型是否被虚拟机支持,以及U盘的文件系统类型(NTFS、exFAT或FAT32等等),在此使用NTFS格式的U盘,openEuler系统无法识别,随后在Windows中格式化U盘、修改其格式为FAT32,成功完成了后续实验。

插入U盘,在虚拟机中设置USB设备:

 

查看U盘盘符:

最后一行/dev/sdb1为U盘。

获取设备号(设备号为8,16):

挂载U盘、挂载devices子系统,并设置U盘拒绝访问:

报错,不支持文件系统,将U盘修改为FAT32格式并继续:

验证:

设置参数使得禁止访问该U盘:

成功,弹出不允许打开U盘的提示。

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
实验二 进程管理   Windows所创建的每个进程都从调用CreateProcess() API函数开始,该函数的任务是在对象管理器子系统内初始化进程对象。每一进程都以调用ExitProcess() 或TerminateProcess() API函数终止。通常应用程序的框架负责调用 ExitProcess() 函数。对于C++ 运行库来说,这一调用发生在应用程序的main() 函数返回之后。 1. 创建进程 CreateProcess() 调用的核心参数是可执行文件运行时的文件名及其命令行。表 2-1详细地列出了每个参数的类型和名称。   表2-1 CreateProcess() 函数的参数 参数名称 使用目的 LPCTSTR lpApplivationName 全部或部分地指明包括可执行代码的EXE文件的文件名 LPCTSTR lpCommandLine 向可执行文件发送的参数 LPSECURIITY_ATTRIBUTES lpProcessAttributes 返回进程句柄的安全属性。主要指明这一句柄是否应该由其他子进程所继承 LPSECURIITY_ATTRIBUTES lpThreadAttributes 返回进程的主线程的句柄的安全属性 BOOL bInheritHandle 一种标志,告诉系统允许新进程继承创建者进程的句柄 DWORD dwCreationFlage 特殊的创建标志 (如CREATE_SUSPENDED) 的位标记 LPVOID lpEnvironment 向新进程发送的一套环境变量;如为null值则发送调用者环境 LPCTSTR lpCurrentDirectory 新进程的启动目录 STARTUPINFO lpStartupInfo STARTUPINFO结构,包括新进程的输入和输出配置的详情 LPPROCESS_INFORMATION lpProcessInformation 调用的结果块;发送新应用程序的进程和主线程的句柄和ID   可以指定第一个参数,即应用程序的名称,其中包括相对于当前进程的当前目录的全路径或者利用搜索方法找到的路径;lpCommandLine参数允许调用者向新应用程序发送数据;接下来的三个参数与进程和它的主线程以及返回的指向该对象的句柄的安全性有关。 然后是标志参数,用以在dwCreationFlags参数中指明系统应该给予新进程什么行为。经常使用的标志是CREATE_SUSPNDED,告诉主线程立刻暂停。当准备好时,应该使用ResumeThread() API来启动进程。另一个常用的标志是CREATE_NEW_CONSOLE,告诉新进程启动自己的控制台窗口,而不是利用父窗口。这一参数还允许设置进程的优先级,用以向系统指明,相对于系统中所有其他的活动进程来说,给此进程多少CPU时间。 接着是CreateProcess() 函数调用所需要的三个通常使用缺省值的参数。第一个参数是lpEnvironment参数,指明为新进程提供的环境;第二个参数是lpCurrentDirectory,可用于向主创进程发送与缺省目录不同的新进程使用的特殊的当前目录;第三个参数是STARTUPINFO数据结构所必需的,用于在必要时指明新应用程序的主窗口的外观。 CreateProcess() 的最后一个参数是用于新进程对象及其主线程的句柄和ID的返回值缓冲区。以PROCESS_INFORMATION结构中返回的句柄调用CloseHandle() API函数是重要的,因为如果不将这些句柄关闭的话,有可能危及主创进程终止之前的任何未释放的资源。 2. 正在运行的进程 如果一个进程拥有至少一个执行线程,则为正在系统中运行的进程。通常,这种进程使用主线程来指示它的存在。当主线程结束时,调用ExitProcess() API函数,通知系统终止它所拥有的所有正在运行、准备运行或正在挂起的其他线程。当进程正在运行时,可以查看它的许多特性,其中少数特性也允许加以修改。 首先可查看的进程特性是系统进程标识符 (PID) ,可利用GetCurrentProcessId() API函数来查看,与GetCurrentProcess() 相似,对该函数的调用不能失败,但返回的PID在整个系统中都可使用。其他的可显示当前进程信息的API函数还有GetStartupInfo()和GetProcessShutdownParameters() ,可给出进程存活期内的配置详情。 通常,一个进程需要它的运行期环境的信息。例如API函数GetModuleFileName() 和GetCommandLine() ,可以给出用在CreateProcess() 中的参数以启动应用程序。在创建应用程序时可使用的另一个
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天涯若

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值