我将一系列 pid
(即 Linux 进程 ID)存储在一个 long
数组中。我意识到 pid
不是 long
,但在使用不同的变量类型方面我别无选择。
当我尝试使用 printf
打印 pid
时,我遇到了这个问题。如果我使用 %ld
打印存储 pid
的 long
,我会得到错误的 pid:
8435315771308 process_ancesto
8358006359962 bash
8353711392665 login
4294967297 init
0 swapper/0
但是,如果我使用 %d
进行打印(这会生成编译器警告),我会得到正确的结果(即通过在终端中键入 ps
返回的结果) :
1969 process_ancesto
1946 bash
1945 login
1 init
0 swapper/0
是什么导致了这种行为? pid -> long 转换是扩大转换,不应引起任何问题。
这是我用来进行返回 pids 的系统调用的程序:
int main(int argc, char *argv[])
{
struct process_info arr[10];
long n=0;
int result = syscall(_CS300_PROCESS_ANCESTORS_, arr,10,&n);
assert(result==0);
for(int i=0;i<n;i++) {
printf("%d %s\n",arr[i].pid,arr[i].name);
}
return 0;
}
如果我将 %d
替换为 %ld
,它会打印不正确的信息。
这是我记录 pid
的系统调用行:
if(copy_long_to_user(&info_array[num_filled_kernel].pid, &curr_task->pid)) {
return -EFAULT;
}
info_array[num_filled_kernel].pid
是一个 long。
最佳答案
两个问题:
在您的 copy_to_user
中,第二个参数是指向 pid_t
的指针,正如您所说,它是一个 int
(32 位).因此,您正在从 32 位变量复制 64 位;如果幸运的话,剩下的 32 位(高半位,因为 x86 是小端字节序)将被内存中接下来的任何内容填充。 (如果你不走运,你会在这里犯错。)当你通过指针访问事物时,不会完成整数转换。
安全地执行此操作的最简单方法是使用临时变量:
long tmp = curr_task->pid; // sign-extension done here
copy_long_to_user(..., &tmp);
然后在您的用户空间代码中,您使用 %d
格式说明符来打印显然是 long
的内容。这行不通; printf
是一个可变参数函数,它不知道其参数应具有的类型,因此无法适本地转换它们。如果您要传递 long
,请使用 %ld
格式说明符。
关于c - 使用 %d 与 %ld 打印 pid,linux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36658863/