21

ユーザー空間からcpusetを使用して、システム内の特定のコアを実際に分離し、そのコアに対して特定のプロセスを 1 つだけ実行できます。

カーネルモジュールで同じことをしようとしています。したがって、モジュールを分離されたコアで実行する必要があります。言い換えれば、カーネルモジュール内から 'sを使用するにはどうすればよいですか? cpuset*

カーネル モジュールでlinux/cpuset.hを使用しても機能しません。したがって、次のようなモジュールがあります。

#include <linux/module.h>
#include <linux/cpuset.h>

...
#ifdef CONFIG_CPUSETS
    printk(KERN_INFO, "cpusets is enabled!");
#endif
cpuset_init(); // this function is declared in cpuset.h
...

このモジュールをロードしようとするとdmesg、次のメッセージが表示されますcpusets is enabled!。しかし、メッセージも受け取りますUnknown symbol cpu_init (err 0)

同様に、実行中のすべてのプロセスを特定のコアに移動し、モジュールを分離されたコアに実行するためにsched_setaffinityfromを使用してみました。linux/sched.h同じエラー メッセージが表示されました: Unknown symbol sched_setaffinity (err 0)EXPORT_SYMBOLこれらの関数にはカーネルがないため、「不明なシンボル」を取得したと思います。sys_sched_setaffinity だから私は行ってシステムコールを呼び出そうとしました(この質問に基づいて)が、再びこのメッセージが表示されました:Unknown symbol sys_sched_setaffinity (err 0)

isolcpusさらに、起動中に設定される を使用するソリューションを探していません。モジュールをロードした後、分離を実行したいと思います。

  • (より正確には、カーネル スレッドを分離されたコアで実行する必要があります。アフィニティを使用してスレッドを特定のコアにバインドできることはわかっていますが、これはコアが実行中の他のプロセスによって分離されることを保証するものではありません。 )
4

4 に答える 4

2

あなたはあなたの質問で指摘しました:

これらの関数にはカーネルに EXPORT_SYMBOL がないため、「不明なシンボル」を取得したと思います

これがあなたの問題の重要なポイントだと思います。linux/cpuset.hメソッドを定義するファイルを含めているようですcpuset_init。ただし、コンパイル中とコマンドの使用中の両方でnm、この関数が使用できないことを示すインジケーターが表示されます。

コンパイル:

root@hectorvp-pc:/home/hectorvp/cpuset/cpuset_try# make
make -C /lib/modules/3.19.0-31-generic/build M=/home/hectorvp/cpuset/cpuset_try modules 
make[1]: Entering directory '/usr/src/linux-headers-3.19.0-31-generic'
  CC [M]  /home/hectorvp/cpuset/cpuset_try/cpuset_try.o
  Building modules, stage 2. 
  MODPOST 1 modules 
  WARNING: "cpuset_init" [/home/hectorvp/cpuset/cpuset_try/cpuset_try.ko] undefined!
  CC      /home/hectorvp/cpuset/cpuset_try/cpuset_try.mod.o
  LD [M]  /home/hectorvp/cpuset/cpuset_try/cpuset_try.ko
make[1]: Leaving directory '/usr/src/linux-headers-3.19.0-31-generic'

を参照してくださいWARNING: "cupset_init" [...] undefined!。そして使用nm

root@hectorvp-pc:/home/hectorvp/cpuset/cpuset_try# nm cpuset_try.ko
0000000000000030 T cleanup_module
                 U cpuset_init
                 U __fentry__
0000000000000000 T init_module
000000000000002f r __module_depends
                 U printk
0000000000000000 D __this_module
0000000000000000 r __UNIQUE_ID_license0
000000000000000c r __UNIQUE_ID_srcversion1
0000000000000038 r __UNIQUE_ID_vermagic0
0000000000000000 r ____versions

(注: U「未定義」の略)

ただし、次のようにカーネルのシンボルを調査しています。

root@hectorvp-pc:/home/hectorvp/cpuset/cpuset_try# cat /proc/kallsyms | grep cpuset_init
ffffffff8110dc40 T cpuset_init_current_mems_allowed
ffffffff81d722ae T cpuset_init
ffffffff81d72342 T cpuset_init_smp

エクスポートされているように見えますが、 では使用できません/lib/modules/$(uname -r)/build/Module.symvers。だからあなたは正しいです。

さらに調査した結果、実際には次のように定義されていることがわかりました。

http://lxr.free-electrons.com/source/kernel/cpuset.c#L2101

これは、カーネル空間で使用できるため、呼び出す必要がある関数です。したがって、ユーザー空間へのアクセスは必要ありません。

モジュールがこのシンボルを呼び出せるようにするために私が見つけた回避策は、この質問の 2 番目の回答で報告されています。もう含める必要がないことにlinux/cpuset.h注意してください:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
//#include <linux/cpuset.h>
#include <linux/kallsyms.h>


int init_module(void)
{
        static void (*cpuset_init_p)(void);
        cpuset_init_p = (void*) kallsyms_lookup_name("cpuset_init");
        printk(KERN_INFO "Starting ...\n");
        #ifdef CONFIG_CPUSETS
            printk(KERN_INFO "cpusets is enabled!");
        #endif
        (*cpuset_init_p)();
        /* 
         * A non 0 return means init_module failed; module can't be loaded. 
         */
        return 0;
}

void cleanup_module(void)
{
        printk(KERN_INFO "Ending ...\n");
}

MODULE_LICENSE("GPL");

私はそれを正常にコンパイルし、インストールしましinsmodた。以下は私が得た出力ですdmesg

[ 1713.738925] Starting ...
[ 1713.738929] cpusets is enabled!
[ 1713.738943] kernel tried to execute NX-protected page - exploit attempt? (uid: 0)
[ 1713.739042] BUG: unable to handle kernel paging request at ffffffff81d7237b
[ 1713.739074] IP: [<ffffffff81d7237b>] cpuset_init+0x0/0x94
[ 1713.739102] PGD 1c16067 PUD 1c17063 PMD 30bc74063 PTE 8000000001d72163
[ 1713.739136] Oops: 0011 [#1] SMP 
[ 1713.739153] Modules linked in: cpuset_try(OE+) xt_conntrack ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 xt_addrtype iptable_filter ip_tables x_tables nf_nat nf_conntrack br_netfilter bridge stp llc pci_stub vboxpci(OE) vboxnetadp(OE) vboxnetflt(OE) vboxdrv(OE) aufs binfmt_misc cfg80211 nls_iso8859_1 snd_hda_codec_hdmi snd_hda_codec_realtek intel_rapl snd_hda_codec_generic iosf_mbi snd_hda_intel x86_pkg_temp_thermal intel_powerclamp snd_hda_controller snd_hda_codec snd_hwdep coretemp kvm_intel amdkfd kvm snd_pcm snd_seq_midi snd_seq_midi_event amd_iommu_v2 snd_rawmidi radeon snd_seq crct10dif_pclmul crc32_pclmul snd_seq_device aesni_intel ttm aes_x86_64 drm_kms_helper drm snd_timer i2c_algo_bit dcdbas mei_me lrw gf128mul mei snd glue_helper ablk_helper
[ 1713.739533]  cryptd soundcore shpchp lpc_ich serio_raw 8250_fintek mac_hid video parport_pc ppdev lp parport autofs4 hid_generic usbhid hid e1000e ahci psmouse ptp libahci pps_core
[ 1713.739628] CPU: 2 PID: 24679 Comm: insmod Tainted: G           OE  3.19.0-56-generic #62-Ubuntu
[ 1713.739663] Hardware name: Dell Inc. OptiPlex 9020/0PC5F7, BIOS A03 09/17/2013
[ 1713.739693] task: ffff8800d29f09d0 ti: ffff88009177c000 task.ti: ffff88009177c000
[ 1713.739723] RIP: 0010:[<ffffffff81d7237b>]  [<ffffffff81d7237b>] cpuset_init+0x0/0x94
[ 1713.739757] RSP: 0018:ffff88009177fd10  EFLAGS: 00010292
[ 1713.739779] RAX: 0000000000000013 RBX: ffffffff81c1a080 RCX: 0000000000000013
[ 1713.739808] RDX: 000000000000c928 RSI: 0000000000000246 RDI: 0000000000000246
[ 1713.739836] RBP: ffff88009177fd18 R08: 000000000000000a R09: 00000000000003db
[ 1713.739865] R10: 0000000000000092 R11: 00000000000003db R12: ffff8800ad1aaee0
[ 1713.739893] R13: 0000000000000000 R14: ffffffffc0947000 R15: ffff88009177fef8
[ 1713.739923] FS:  00007fbf45be8700(0000) GS:ffff88031dd00000(0000) knlGS:0000000000000000
[ 1713.739955] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1713.739979] CR2: ffffffff81d7237b CR3: 00000000a3733000 CR4: 00000000001407e0
[ 1713.740007] Stack:
[ 1713.740016]  ffffffffc094703e ffff88009177fd98 ffffffff81002148 0000000000000001
[ 1713.740052]  0000000000000001 ffff8802479de200 0000000000000001 ffff88009177fd78
[ 1713.740087]  ffffffff811d79e9 ffffffff810fb058 0000000000000018 ffffffffc0949000
[ 1713.740122] Call Trace:
[ 1713.740137]  [<ffffffffc094703e>] ? init_module+0x3e/0x50 [cpuset_try]
[ 1713.740175]  [<ffffffff81002148>] do_one_initcall+0xd8/0x210
[ 1713.740190]  [<ffffffff811d79e9>] ? kmem_cache_alloc_trace+0x189/0x200
[ 1713.740207]  [<ffffffff810fb058>] ? load_module+0x15b8/0x1d00
[ 1713.740222]  [<ffffffff810fb092>] load_module+0x15f2/0x1d00
[ 1713.740236]  [<ffffffff810f6850>] ? store_uevent+0x40/0x40
[ 1713.740250]  [<ffffffff810fb916>] SyS_finit_module+0x86/0xb0
[ 1713.740265]  [<ffffffff817ce10d>] system_call_fastpath+0x16/0x1b
[ 1713.740280] Code: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0c 53 58 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <00> 00 00 00 00 1c 00 00 00 c0 92 2c 7d c0 92 2c 7d a0 fc 69 ee 
[ 1713.740398] RIP  [<ffffffff81d7237b>] cpuset_init+0x0/0x94
[ 1713.740413]  RSP <ffff88009177fd10>
[ 1713.740421] CR2: ffffffff81d7237b
[ 1713.746177] ---[ end trace 25614103c0658b94 ]---

エラーにもかかわらず、私はあなたの最初の質問に答えたと思います:

カーネルモジュール内から cpuset を使用するにはどうすればよいですか? *

私はまったく専門家ではないので、おそらく最もエレガントな方法ではありません。ここから続ける必要があります。

よろしく

于 2016-04-07T15:40:14.513 に答える
0

でwork_structを試しましたか

struct workqueue_attrs {
cpumask_var_t           cpumask;        /* allowed CPUs */
}

まず、CPU を (たとえば、cpu 0x1) 経由で分離する必要があります。

setenv bootargs isolcpus=\"0x1"\

そして次

struct lkm_sample {
struct work_struct lkm_work_struct;
struct workqueue_struct *lkm_wq_struct;
...
};
static struct lkm_sample lkm_smpl;

static void work(struct work_struct *work)
{
struct lkm_sample *tmp = container_of(work, struct lkm_sample,     lkm_work_struct);
....
return;
}
static int __init lkm_init(void)
{
//see:     https://lwn.net/Articles/540999/
lkm_smpl.lkm_wq_struct = create_singlethread_workqueue("you_wq_name");
INIT_WORK(&lkm_smpl.lkm_wq_struct, work);
}

独立した CPU で lkm を開始 (__init を実行) したい場合:

  1. setenv bootargs isolcpus=\"0x1"\

  2. lsmod helper_module.ko と

    call_usermodehelper_setup struct subprocess_info * call_usermodehelper_setup ( char * path, char ** argv, /*taskset 0x00000001 helper_application */ char ** envp, gfp_t gfp_mask, int (*init) (struct subprocess_info *info, struct cred *new), void (* cleanup) (struct subprocess_info *info), void * data); タスクセットを介してユーザー空間プログラム (helper_application) を実行するヘルパー カーネル モジュールを使用し、マスクは isolcpus から取得する必要があります。ヘルパー モジュールは __init function() のみを実行し、-1 を返す必要があります。これは、分離された CPU でユーザー空間アプリを実行するタスクが 1 つだけであるためです。

  3. 次のユーザー空間ヘルパー アプリケーションは次のとおりです。goal_module.ko の lsmod、goal_module は同じ分離された CPU で開始する必要があります。

  4. workqueue を使用して、分離された CPU で分離されたモジュールを実行し続けます。

于 2016-04-04T05:56:27.610 に答える