打印pid与%d对%ld,linux [英] printing pid with %d vs %ld, linux
问题描述
我将一系列 pid
(即Linux进程ID)存储在 long
。我意识到 pid
不是 long
,但是我没有选择使用不同的变量类型。
I'm storing a series of pid
s (i.e. Linux process ids) in an array of long
s. I realize that a pid
is not a long
, but I have no choice in terms of using a different variable type.
当我尝试使用 printf打印
。如果我打印使用 pid
%ld
pid 的 long
>,我得到错误的pids:
The issue I'm having occurs when I try and print the pid
using printf
. If I print the long
that stores the pid
using %ld
, I get the wrong pids:
8435315771308 process_ancesto
8358006359962 bash
8353711392665 login
4294967297 init
0 swapper/0
但是,如果我使用%d
(生成编译器警告),我得到正确的结果(即通过在终端中键入 ps
返回的结果):
However, if I print using %d
(which generates a compiler warning), I get the correct result (i.e. the result returned by typing ps
into the terminal):
1969 process_ancesto
1946 bash
1945 login
1 init
0 swapper/0
导致此行为的原因是什么? A pid - > long cast是一个扩展的转换,不应该引起任何问题。
What is causing this behaviour? A pid -> long cast is a widening conversion and shouldn't cause any problems.
这里是我用来做系统调用返回pids的程序: / p>
Here is the program I use to make the system call that returns the 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
它打印不正确的信息。
If I replace the %d
with %ld
it prints incorrect info.
这是从我的系统调用, pid
:
Here is the line from my system call where I record the pid
:
if(copy_long_to_user(&info_array[num_filled_kernel].pid, &curr_task->pid)) {
return -EFAULT;
}
info_array [num_filled_kernel] .pid $ c
info_array[num_filled_kernel].pid
is a long.
有两个问题:
推荐答案
在 copy_to_user
中,第二个参数是指向 pid_t
的指针,它出现, c $ c> int (32位)。所以你从一个32位变量复制64位;剩下的32位(高一半,因为x86是小端序)将填充任何内存中的下一个,如果你是幸运的。
In your copy_to_user
, the second argument is a pointer to pid_t
, it appears, which as you say is an int
(32 bits). So you are copying 64 bits from a 32-bit variable; the remaining 32 bits (the high half, since x86 is little-endian) will be filled with whatever came next in memory, if you are lucky. (If you are unlucky you get a fault here.) Integer conversions aren't done when you access things via pointers.
安全地执行这个操作的最简单的方法是使用一个临时变量:
The simplest way to do this safely is to use a temporary variable:
long tmp = curr_task->pid; // sign-extension done here
copy_long_to_user(..., &tmp);
然后在用户空间代码中,使用%d
格式说明符打印显然是
long
的东西。这不会工作; printf
是一个可变函数,不知道它的参数应该具有的类型,因此不能适当地转换它们。如果您要通过长
,请使用%ld
格式说明符。
Then in your user space code, you are using the %d
format specifier to print something that's apparently a long
. This won't work; printf
, being a variadic function, doesn't know the type that its arguments are expected to have, and so can't convert them appropriately. If you're going to pass a long
, use the %ld
format specifier.
这篇关于打印pid与%d对%ld,linux的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!