terrace
驱动牛犊
驱动牛犊
  • 注册日期2004-02-11
  • 最后登录2005-12-04
  • 粉丝0
  • 关注0
  • 积分15分
  • 威望3点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1500回复:4

请问如何在LINUX KERNEL 下运行(用户)程序?

楼主#
更多 发布于:2004-02-19 10:33
各位大侠,我实在不知该怎样定标题,或许标题就很弱质,但意思如下:
我想写一个找到PCI总线上设备的小程序(输入VENDOR ID 和DEVICE ID,
终端上显示其BUS# DEV# FUNC#以及该设备的IoBaseAddr).其中要使用KERNEL下的对端口的输入输出操作.我写了一个很奇怪的程序:

#define __KERNEL__
#include<linux/kernel.h>
#include<asm/io.h>
#define IC_SIGNATURE  0x244b8086
#define MAX_BUS_NUM 4
#define MAX_DEV_NUM 0x20
#define MAX_FUNC_NUM 8
#define USHORT unsigned short
typedef struct  {
        USHORT reg_num :8;
        USHORT fun_num :3;
        USHORT dev_num :5;
        USHORT bus_num :8;
        USHORT reserved:7;
        USHORT enable  :1;
}PCI_CFG_ADDR,*PPCI_CFG_ADDR;
 
PCI_CFG_ADDR pci_cfg={0,};
unsigned long IoBaseAddr;
unsigned long location;
 
int find_adapter()
{
        unsigned int bus,dev,func;
        unsigned long signature;
        unsigned long *lp;
        unsigned char ch0,ch1,ch2,ch3;
        int find_device=0;
        pci_cfg.enable=1;
        pci_cfg.reg_num=0;
        for(bus=0;bus<MAX_BUS_NUM;bus++) {
           for(dev=0;dev<MAX_DEV_NUM;dev++) {
              for(func=0;func<MAX_FUNC_NUM;func++){
                        pci_cfg.bus_num=bus;
                        pci_cfg.dev_num=dev;
                        pci_cfg.fun_num=func;
 
                        lp=(unsigned long *)&pci_cfg;
                        /*
                        ch0=*((char *)lp+0);
                        ch1=*((char *)lp+1);
                        ch2=*((char *)lp+2);
                        ch3=*((char *)lp+3);*/
                        outl_p(*lp,0xcf8);
                        signature=inl_p(0xcfc);
                        if(signature==IC_SIGNATURE)
                                {
                                    find_device=1;
                                    break;
                                }
                }
               if(find_device==1) break;
              }
            if(find_device==1) break;
        }
 
        if(find_device){
                pci_cfg.reg_num=0x20;
                lp=(unsigned long *) &pci_cfg;
                location=*lp;
                outl_p(0xcf8,*lp);
                IoBaseAddr=inl(0xcfc);
        }
        return find_device;
}
 
int main(void)
{
        if(find_adapter()) {
                printk("<5>FIND HARDDEVICE!\n");
                printk("<5>location:%ld,IoBaseAddr:%ld\n",location,IoBaseAddr);
                return 1;
        }else{
                printk("<5>FINDING DEVICE ERROR!\n");
                return 0;
             }
}

结果编译正常,运行时却说"段错误".
我知道有问题,但也说不出个所以然,另外,请问我该怎么办才能达到目的?
万分感激!
kernel_1998
驱动牛犊
驱动牛犊
  • 注册日期2004-02-19
  • 最后登录2004-10-20
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-02-19 13:10
代码没什么问题,只不过用的方式错了。不过可以理解,任何人开始的时候都会犯这个错误。
solution:
   你编译出来的程序是一个只能在用户态下运行的应用程序。它是不能访问IO地址空间的,这是你出错的主要原因;
   我估计你读过一些PCI方面的资料,但对OS不是很了解,这里提供两个建议
(1)你要进行这样的操作,必须使用模块的方式,可以到网上找一些linux loadable module方面的资料,把你的program该成init_module和exit_module的形式。(记得操作的时候读一下就可以了,尽量不要写)《linux device driver》2nd是一个不错的开始。
(2)《Linux内核源代码情景分析》的下册设备驱动一章有对PCI操作的分析,可以一看。
terrace
驱动牛犊
驱动牛犊
  • 注册日期2004-02-11
  • 最后登录2005-12-04
  • 粉丝0
  • 关注0
  • 积分15分
  • 威望3点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-02-19 13:54
kernel_1998:
    一语惊醒梦中人!
    非常感谢!
    我现在正在测试初建安装并调用module的实验.但有个小问题,还望解答:
    我写了个module (test.c),并编译成功,而且安装,并创立了设备文件.但是运行test_app.c时,却显示cannot open file!.
我查了下 /dev/test文件,大小为0.请问到底哪里有问题?
是module(test.c) 还是test_app.c?
源码如下:
[root@terrace root]# cat test.c
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<asm/uaccess.h>
 
static char *pMessage="just for test!aaaaaaaaaaaaaaaaaaaaaaaaa";
/*
static struct file_operations test_fops={
        read:test_read,
        write:test_write,
        open:test_open,
        release:test_release,
};
*/
static unsigned int test_major =0;
static int test_read(struct file *file,char *buf,size_t length,loff_t *offset)
{
        int bytes_read=0;
        if(*pMessage==0)
        return 0;
        while(length&& *pMessage){
            put_user(*(pMessage++),buf++);
            length--;
            bytes_read++;
        }
        printk("<1>Read %d bytes,%d left\n",bytes_read,length);
        return bytes_read;
}
 
static size_t test_write(struct file *file,const char *buf,size_t length,loff_t *offset)
{
        return -EINVAL;
}
static int test_open(struct inode *inode,struct file *fle)
{
        MOD_INC_USE_COUNT;
        return 0;
}
static void test_release(struct inode *inode,struct file *file)
{
        MOD_DEC_USE_COUNT;
}
 
static struct file_operations test_fops={
        read:test_read,
        write:test_write,
        open:test_open,
        release:test_release,
};
 
int init_module(void)
{
        int result=register_chrdev(0,"test",&test_fops);
        if(result<0){
                printk("<1>test:can't get major number!\n");
                return result;
                if (test_major==0)
                  test_major=result;
        }
        return 0;
}
 
void clean_module(void)
{
        unregister_chrdev(test_major,"test");
}
[root@terrace root]# cat test_app.c
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
 
int main()
{
        int testdev;
        int i;
        char buf[20];
        testdev=open("/dev/test",O_RDONLY);
        if(testdev =-1){
                printf("cannot open file!\n");
                exit(0);
        }
        read(testdev,buf,20);
        for(i=0;i<20;i++)
            printf("%c",buf);
        close(testdev);
}
[root@terrace root]#
unix1998
驱动老牛
驱动老牛
  • 注册日期2002-05-08
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-02-20 09:48
别把kernel和user弄在一起啊,那岂不是很不稳定?
enLinux
驱动牛犊
驱动牛犊
  • 注册日期2003-11-27
  • 最后登录2007-10-29
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望2点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-02-22 18:18
本人刚发了一个附件,不知道管理员会不会接受,内容与你的要求类试,有源代码
解压后,./setup, showpci
-l 显示大部分信息
-v num 表示vendor id
-d num 表示device id
-c num 表示class id
三个num都可以在pci_ids.h中指定的值中找到

如果你不知道任何一个id
可以执行showpci, 找到对应的id,
showpci -l -v num -d num -c num

在X下,执行后察看sys log

[编辑 -  2/22/04 by  enLinux]
附件名称/大小 下载次数 最后更新
2004-02-22_showpci.tar.gz (5KB)  1
游客

返回顶部