替换Linux内核中使用的container_of宏

时间:2018-09-06 06:04:51

标签: c linux

在尝试从源代码Linux内核Definition of container_of理解 container_of()的功能时,我发现宏定义的以下行似乎无所事事。

  

const typeof((((type *)0)-> member)* __ mptr =(ptr); \

因此,我编写了一个不带上述行的简单C程序,并尝试比较所获得的结果。 基本上,我试图理解新的实现 my_contianer_of() container_of() 有何不同?

public class MainActivity extends AppCompatActivity {

    LinearLayout verticallayout,horizontalLayout; //got

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        verticallayout = findViewById(R.id.verticalLayout); //got

    }

    public void createRow(View view){

        createRow(); //got

    }



    private void createRow() { //got

        horizontalLayout = new LinearLayout(this);

        LinearLayout.LayoutParams horizontalParams = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        horizontalLayout.setOrientation(LinearLayout.HORIZONTAL);
        horizontalParams.setMargins(15, 5, 15, 5); // LEFT, TOP, RIGHT, BOTTOM
        horizontalLayout.setLayoutParams(horizontalParams);


        createSpinner();
        createCheckbox();
        createEditText();

        verticallayout.addView(horizontalLayout, horizontalParams);
    }








    private void createEditText() {
        EditText editText = new EditText(this);

        LinearLayout.LayoutParams editParams = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        editParams.setMargins(10, 10, 10, 10);

        editText.setLayoutParams(editParams);
        horizontalLayout.addView(editText);
    }


    private void createCheckbox() { //done
        CheckBox checkBox = new CheckBox(this);

        LinearLayout.LayoutParams checkParams = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        checkParams.setMargins(10, 10, 10, 10);
        checkParams.gravity = Gravity.LEFT;

        checkBox.setLayoutParams(checkParams);
        horizontalLayout.addView(checkBox);

    }

    private void createSpinner() {

        Spinner spinner = new Spinner(this);
        //ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_dropdown_item, spinnerArray);
        //spinner.setAdapter(spinnerArrayAdapter);
        LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        spinnerParams.setMargins(10, 10, 10, 10);
        spinnerParams.gravity = Gravity.LEFT;

        spinner.setLayoutParams(spinnerParams);
        horizontalLayout.addView(spinner);
    }
}

以下是上述c程序的示例输出。

#include <stdio.h>
#include <stddef.h>

#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

#define my_container_of(ptr, type, member) ({ \
        (char *)ptr - offsetof(type, member);})

struct container {
    int *i;
    char c;
    float f;
};

void foo(char *cptr)
{
    printf("foo  : %p\n", my_container_of(cptr, struct container, c));
}

int main(int argc, char *argv[])
{
    struct container tc;

    printf("&tc  : %p\n", &tc);
    printf("cof  : %p\n", container_of(&tc.c, struct container, c));
    printf("mycof: %p\n", my_container_of(&tc.c, struct container, c));

    foo(&tc.c);

    return 0;
}

请不要将此问题标记为任何其他问题或此Understanding container_of macro in the linux kernel的重复,因为这些问题没有为我的查询提供所需的答案。

1 个答案:

答案 0 :(得分:2)

您的实现类型不安全。它不能确保您传递的指针与该成员具有相同的类型,这可能会导致错误。因此,例如:

my_container_of(&tc.f, struct container, c)

编译就可以了。内核版本至少会发出有关不兼容的指针类型的警告。还是完全清除,导致编译停止,具体取决于您的GCC标志。

自然地,内核版本不能防止所有错误(例如,如果fc属于同一类型)。但这是可以捕获的,应该捕获。