Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Modeler   Code  
»áÔ±   
 
   
 
 
     
   
 ¶©ÔÄ
  ¾èÖú
Linux×Ö·ûÉ豸Çý¶¯¿ò¼Ü
 
À´Ô´£º51CTO ·¢²¼ÓÚ 2017-2-17
  2254  次浏览      27
 

×Ö·ûÉ豸ÊÇLinuxÈý´óÉ豸֮һ(ÁíÍâÁ½ÖÖÊÇ¿éÉ豸£¬ÍøÂçÉ豸)£¬×Ö·ûÉ豸¾ÍÊÇ×Ö½ÚÁ÷ÐÎʽͨѶµÄI/OÉ豸,¾ø´ó²¿·ÖÉ豸¶¼ÊÇ×Ö·ûÉ豸£¬³£¼ûµÄ×Ö·ûÉ豸°üÀ¨Êó±ê¡¢¼üÅÌ¡¢ÏÔʾÆ÷¡¢´®¿ÚµÈµÈ£¬µ±ÎÒÃÇÖ´ÐÐls -l /devµÄʱºò£¬¾ÍÄÜ¿´µ½´óÁ¿µÄÉ豸Îļþ£¬c¾ÍÊÇ×Ö·ûÉ豸£¬b¾ÍÊÇ¿éÉ豸£¬ÍøÂçÉ豸ûÓжÔÓ¦µÄÉ豸Îļþ¡£±àдһ¸öÍⲿģ¿éµÄ×Ö·ûÉ豸Çý¶¯£¬³ýÁËҪʵÏÖ±àдһ¸öÄ£¿éËùÐèÒªµÄ´úÂëÖ®Í⣬»¹ÐèÒª±àд×÷Ϊһ¸ö×Ö·ûÉ豸µÄ´úÂë¡£

Çý¶¯Ä£ÐÍ

LinuxÒ»ÇнÔÎļþ£¬ÄÇô×÷Ϊһ¸öÉ豸Îļþ£¬ËüµÄ²Ù×÷·½·¨½Ó¿Ú·â×°ÔÚstruct file_operations£¬µ±ÎÒÃÇдһ¸öÇý¶¯µÄʱºò£¬Ò»¶¨ÒªÊµÏÖÏàÓ¦µÄ½Ó¿Ú£¬ÕâÑù²ÅÄÜʹÕâ¸öÇý¶¯¿ÉÓã¬LinuxµÄÄÚºËÖдóÁ¿Ê¹ÓÃ"×¢²á+»Øµ÷"»úÖÆ½øÐÐÇý¶¯³ÌÐòµÄ±àд£¬Ëùνע²á»Øµ÷£¬¼òµ¥µÄÀí½â£¬¾ÍÊǵ±ÎÒÃÇopenÒ»¸öÉ豸ÎļþµÄʱºò£¬ÆäʵÊÇͨ¹ýVFSÕÒµ½ÏàÓ¦µÄinode£¬²¢Ö´ÐдËǰ´´½¨Õâ¸öÉ豸Îļþʱע²áÔÚinodeÖеÄopenº¯Êý£¬ÆäËûº¯ÊýÒ²ÊÇÈç´Ë£¬ËùÒÔ£¬ÎªÁËÈÃÎÒÃÇдµÄÇý¶¯Äܹ»Õý³£µÄ±»Ó¦ÓóÌÐò²Ù×÷£¬Ê×ÏÈÒª×öµÄ¾ÍÊÇʵÏÖÏàÓ¦µÄ·½·¨£¬È»ºóÔÙ´´½¨ÏàÓ¦µÄÉ豸Îļþ¡£

#include <linux/cdev.h> //for struct cdev 
#include <linux/fs.h> //for struct file
#include <asm-generic/uaccess.h> //for copy_to_user
#include <linux/errno.h> //for error number

static int ma = 0;
static int mi = 0;
const int count = 3;/* ×¼±¸²Ù×÷·½·¨¼¯ *//*
struct file_operations {
struct module *owner; //THIS_MODULE

//¶ÁÉ豸
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
//дÉ豸
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

//Ó³ÉäÄں˿ռ䵽Óû§¿Õ¼ä
int (*mmap) (struct file *, struct vm_area_struct *);

//¶ÁдÉ豸²ÎÊý¡¢¶ÁÉ豸״̬¡¢¿ØÖÆÉ豸
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

//´ò¿ªÉ豸
int (*open) (struct inode *, struct file *);
//¹Ø±ÕÉ豸
int (*release) (struct inode *, struct file *);

//Ë¢ÐÂÉ豸
int (*flush) (struct file *, fl_owner_t id);

//Îļþ¶¨Î»
loff_t (*llseek) (struct file *, loff_t, int);

//Ò첽֪ͨ
int (*fasync) (int, struct file *, int);
//POLL»úÖÆ
unsigned int (*poll) (struct file *, struct poll_table_struct *);
¡£¡£¡£
};
*/

ssize_t myread(struct file *filep, char __user * user_buf, size_t size,
loff_t* offset)
{ return 0;
}
struct file fops = {
.owner = THIS_MODULE,
.read = myread£¬
...
};/* ×Ö·ûÉ豸¶ÔÏóÀàÐÍ
struct cdev {
struct kobject kobj;
struct module *owner; //Ä£¿éËùÓÐÕߣ¨THIS_MODULE£©£¬ÓÃÓÚÄ£¿é¼ÆÊý
const struct file_operations *ops;//²Ù×÷·½·¨¼¯£¨·Ö¹¤:´ò¿ª¡¢¹Ø±Õ¡¢¶Á/д¡¢...£©
struct list_head list;
dev_t dev; //É豸ºÅ£¨µÚÒ»¸ö£©
unsigned int count; //É豸ÊýÁ¿
};
*/static int __init chrdev_init(void){
... /* ¹¹ÔìcdevÉ豸¶ÔÏó */
struct cdev *cdev_alloc(void); /* ³õʼ»¯cdevÉ豸¶ÔÏó */
void cdev_init(struct cdev*, const struct file_opeartions*);
/* ÉêÇëÉ豸ºÅ£¬¾²Ì¬or¶¯Ì¬*/
/* Ϊ×Ö·ûÉ豸¾²Ì¬ÉêÇëµÚÒ»¸öÉ豸ºÅ */
int register_chrdev_region(dev_t from, unsigned count, const char* name);
/* Ϊ×Ö·ûÉ豸¶¯Ì¬ÉêÇëµÚÒ»¸öÉ豸ºÅ */
int alloc_chrdev_region(dev_t* dev, unsigned baseminor, unsigned count,
const char* name);

ma = MAJOR(dev) //´Ódev_tÊý¾ÝÖеõ½Ö÷É豸ºÅ
mi = MINOR(dev) //´Ódev_tÊý¾ÝÖеõ½´ÎÉ豸ºÅ
MKDEV(ma,1) //½«Ö÷É豸ºÅºÍ´ÎÉ豸ºÅ×éºÏ³ÉÉ豸ºÅ,¶àÓÃÓÚÅúÁ¿´´½¨/ɾ³ýÉ豸Îļþ

/* ×¢²á×Ö·ûÉ豸¶ÔÏócdevµ½ÄÚºË */
int cdev_add(struct cdev* , dev_t, unsigned);
...
}static void __exit chrdev_exit(void){
... /* cdev_del()¡¢cdev_put()¶þѡһ */
/* ´ÓÄÚºË×¢ÏúcdevÉ豸¶ÔÏó */
void cdev_del(struct cdev* ); /* ´ÓÄÚºË×¢ÏúcdevÉ豸¶ÔÏó */
void cdev_put(stuct cdev *); /* »ØÊÕÉ豸ºÅ */
void unregister_chrdev_region(dev_t from, unsigned count);

ÂÞàÂÒ»¾ä£¬Èç¹ûʹÓþ²Ì¬ÉêÇëÉ豸ºÅ£¬ÄÇô×î´óµÄÎÊÌâ¾ÍÊDz»ÒªÓëÒÑÖªµÄÉ豸ºÅÏà³åÍ»£¬ÄÚºËÔÚÎĵµ"Documentation/devices.txt"ÖÐÒѾ­×¢Ã÷ÁËÄÄЩÖ÷É豸ºÅ±»Ê¹ÓÃÁË£¬´ÓÖпÉÒÔ¿´³ö£¬ÔÚ2^12¸öÖ÷É豸ºÅÖУ¬ÎÒÃÇÄܹ»Ê¹Óõķ¶Î§ÊÇ240-255ÒÔ¼°261-2^12-1µÄ²¿·Ö£¬ÕâÒ²¿ÉÒÔ½âÊÍΪʲôÎÒÃǶ¯Ì¬ÉêÇëµÄʱºò£¬É豸ºÅ¾­³£ÊÇ250µÄÔ­Òò¡£´ËÍ⣬ͨ¹ýÕâ¸öÎļþ£¬ÎÒÃÇÒ²¿ÉÒÔ¿´³ö£¬"Ö÷É豸ºÅ±íÕ÷Ò»ÀàÉ豸"£¬µ«ÊÇ×Ö·û/¿éÉ豸±¾Éí¾Í¿ÉÒÔ±»·ÖΪºÃ¶àÀ࣬ËùÒÔÄں˸øËûÃÇÿһÀà¶¼·ÖÅäÁËÖ÷É豸ºÅ¡£

ʵÏÖread£¬write

Linuxϸ÷¸ö½ø³Ì¶¼ÓÐ×Ô¼º¶ÀÁ¢µÄ½ø³Ì¿Õ¼ä£¬¼´Ê¹Êǽ«Äں˵ÄÊý¾ÝÓ³Éäµ½Óû§½ø³Ì£¬¸ÃÊý¾ÝµÄPIDÒ²»á×Ô¶¯×ª±äΪ¸ÃÓû§½ø³ÌµÄPID£¬ÓÉÓÚÕâÖÖ»úÖÆµÄ´æÔÚ£¬ÎÒÃDz»ÄÜÖ±½Ó½«Êý¾Ý´ÓÄں˿ռäºÍÓû§¿Õ¼ä½øÐп½±´£¬¶øÐèҪרÃŵĿ½±´Êý¾Ýº¯Êý/ºê£º

long copy_from_user(void *to, const void __user * from, unsigned long n) 
long copy_to_user(void __user *to, const void *from, unsigned long n)

ÕâÁ½¸öº¯Êý¿ÉÒÔ½«Äں˿ռäµÄÊý¾Ý¿½±´µ½»Øµ÷¸Ãº¯ÊýµÄÓû§½ø³ÌµÄÓû§½ø³Ì¿Õ¼ä£¬ÓÐÁËÕâÁ½¸öº¯Êý£¬ÄÚºËÖеÄread,write¾Í¿ÉÒÔʵÏÖÄں˿ռäºÍÓû§¿Õ¼äµÄÊý¾Ý¿½±´¡£

ssize_t myread(struct file *filep, char __user * user_buf, size_t size, loff_t* offset) 
{
long ret = 0;
size = size > MAX_KBUF?MAX_KBUF:size;
if(copy_to_user(user_buf, kbuf,size)
return -EAGAIN;
}
return 0;
}

ʵÏÖioctl

ioctlÊÇLinuxרÃÅΪÓû§²ã¿ØÖÆÉ豸Éè¼ÆµÄϵͳµ÷Óýӿڣ¬Õâ¸ö½Ó¿Ú¾ßÓм«´óµÄÁé»îÐÔ£¬ÎÒÃǵÄÉ豸´òËãÈÃÓû§Í¨¹ýÄÄЩÃüÁîʵÏÖÄÄЩ¹¦ÄÜ£¬¶¼¿ÉÒÔͨ¹ýËüÀ´ÊµÏÖ£¬ioctlÔÚ²Ù×÷·½·¨¼¯ÖжÔÓ¦µÄº¯ÊýÖ¸ÕëÊÇlong (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);£¬ÆäÖеÄÃüÁîºÍ²ÎÊýÍêÈ«ÓÉÇý¶¯Ö¸¶¨£¬Í¨³£ÃüÁî»áдÔÚÒ»¸öÍ·ÎļþÖÐÒÔ¹©Ó¦ÓòãºÍÇý¶¯²ã×ñÊØÍ¬ÑùµÄͨÐÅЭÒ飬Linux½¨ÒéÈçͼËùʾµÄ·½Ê½¶¨Òåioctl()ÃüÁî

É豸ÀàÐÍ×Ö¶ÎΪһ¸ö»ÃÊý£¬¿ÉÒÔÊÇ0~0xffÖ®¼äµÄÊý£¬ÄÚºËÖеÄ"ioctl-number.txt"¸ø³öÁËÒ»¸öÍÆ¼öµÄºÍÒѾ­±»Ê¹ÓõĻÃÊý(µ«ÊÇÒѾ­ºÃ¾ÃûÈËά»¤ÁË)£¬ÐÂÉ豸Çý¶¯¶¨Òå»ÃÊýµÄʱºòÒª±ÜÃâÓëÆä³åÍ»¡£

ÐòÁкÅ×ֶαíʾµ±Ç°ÃüÁîÊÇÕû¸öioctlÃüÁîÖеĵڼ¸¸ö£¬´Ó1¿ªÊ¼¼ÆÊý¡£

·½Ïò×Ö¶ÎΪ2bit£¬±íʾÊý¾ÝµÄ´«Êä·½Ïò£¬¿ÉÄܵÄÖµÊÇ£º_IOC_NONE£¬_IOC_READ£¬_IOC_WRITEºÍ_IOC_READ|_IOC_WRITE¡£

Êý¾Ý³ß´ç×ֶαíÊ¾Éæ¼°µÄÓû§Êý¾ÝµÄ´óС£¬Õâ¸ö³ÉÔ±µÄ¿í¶ÈÒÀÀµÓÚÌåϵ½á¹¹£¬Í¨³£ÊÇ13»ò14λ¡£

Äں˻¹¶¨ÒåÁË_IO()£¬_IOR()£¬_IOW()£¬_IOWR()Õâ4¸öºêÀ´¸¨ÖúÉú³ÉÕâÖÖ¸ñʽµÄÃüÁî¡£Õ⼸¸öºêµÄ×÷ÓÃÊǸù¾Ý´«ÈëµÄtype(É豸ÀàÐÍ×Ö¶Î)£¬nr(ÐòÁкÅ×Ö¶Î)ºÍsize(Êý¾Ý³¤¶È×Ö¶Î)ºÍ·½Ïò×Ö¶ÎÒÆÎ»×éºÏÉú³ÉÃüÁîÂë¡£

ÄÚºËÖл¹Ô¤¶¨ÒåÁËһЩI/O¿ØÖÆÃüÁÈç¹ûijÉ豸Çý¶¯Öаüº¬ÁËÓëÔ¤¶¨ÒåÃüÁîÒ»ÑùµÄÃüÁîÂ룬ÕâЩÃüÁî»á±»µ±×öÔ¤¶¨ÒåÃüÁî±»Äں˴¦Àí¶ø²»ÊDZ»É豸Çý¶¯´¦Àí£¬ÓÐÈçÏÂ4ÖÖ:

FIOCLEX:¼´file ioctl close on exec ¶ÔÎļþÉèÖÃרÓõıêÖ¾£¬Í¨ÖªÄں˵±exec()ϵͳ´øÅ¶Ó÷¢Éúʱ×Ô¶¯¹Ø±Õ´ò¿ªµÄÎļþ

FIONCLEX:¼´file ioctl not close on exec£¬Çå³ýÓÉFIOCLEXÉèÖõıêÖ¾

FIOQSIZE:»ñµÃÒ»¸öÎļþ»òĿ¼µÄ´óС£¬µ±ÓÃÓÚÉ豸Îļþʱ£¬·µ»ØÒ»¸öENOTTY´íÎó

FIONBIO:¼´file ioctl non-blocking I/O Õâ¸öµ÷ÓÃÐÞ¸Äflip->f_flagsÖеÄO_NONBLOCK±êÖ¾

ʵÀý

//mycmd.h...#include <asm/ioctl.h>#define CMDT 'A'#define KARG_SIZE 
36struct karg{ int kval; char kbuf[KARG_SIZE];
};#define CMD_OFF _IO(CMDT,0)#define CMD_ON _IO(CMDT,1)#define CMD_R
_IOR(CMDT,2,struct karg)#define CMD_W _IOW(CMDT,3,struct karg)...

//chrdev.c 

static long demo_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
static struct karg karg = {
.kval = 0,
.kbuf = {0},
};
struct karg *usr_arg;
switch(cmd){
case CMD_ON: /* ¿ªµÆ */
break;
case CMD_OFF: /* ¹ØµÆ */
break;
case CMD_R:
if(_IOC_SIZE(cmd) != sizeof(karg)){
return -EINVAL;
}
usr_arg = (struct karg *)arg;

if(copy_to_user(usr_arg, &karg, sizeof(karg))){
return -EAGAIN;
}
break;
case CMD_W:
if(_IOC_SIZE(cmd) != sizeof(karg)){
return -EINVAL;
}
usr_arg = (struct karg *)arg;
if(copy_from_user(&karg, usr_arg, sizeof(karg))){ return -EAGAIN;
}
break;
default:
;
};
return 0;}

´´½¨É豸Îļþ

²åÈëµÄÉ豸ģ¿é£¬ÎÒÃǾͿÉÒÔʹÓÃcat /proc/devicesÃüÁî²é¿´µ±Ç°ÏµÍ³×¢²áµÄÉ豸£¬µ«ÊÇÎÒÃÇ»¹Ã»Óд´½¨ÏàÓ¦µÄÉ豸Îļþ£¬Óû§Ò²¾Í²»ÄÜͨ¹ýÎļþ·ÃÎÊÕâ¸öÉ豸¡£É豸ÎļþµÄinodeÓ¦¸ÃÊǰüº¬ÁËÕâ¸öÉ豸µÄÉ豸ºÅ£¬²Ù×÷·½·¨¼¯Ö¸ÕëµÈÐÅÏ¢£¬ÕâÑùÎÒÃǾͿÉÒÔͨ¹ýÉ豸ÎļþÕÒµ½ÏàÓ¦µÄinode½ø¶ø·ÃÎÊÉ豸¡£´´½¨É豸ÎļþµÄ·½·¨ÓÐÁ½ÖÖ£¬ÊÖ¶¯´´½¨»ò×Ô¶¯´´½¨£¬ÊÖ¶¯´´½¨É豸Îļþ¾ÍÊÇʹÓÃmknod /dev/xxx É豸ÀàÐÍ Ö÷É豸ºÅ ´ÎÉ豸ºÅµÄÃüÁî´´½¨£¬ËùÒÔÊ×ÏÈÐèҪʹÓÃcat /proc/devices²é¿´É豸µÄÖ÷É豸ºÅ²¢Í¨¹ýÔ´ÂëÕÒµ½É豸µÄ´ÎÉ豸ºÅ£¬ÐèҪעÒâµÄÊÇ£¬ÀíÂÛÉÏÉ豸Îļþ¿ÉÒÔ·ÅÖÃÔÚÈκÎÎļþ¼Ó¼Ð£¬µ«ÊǷŵ½"/dev"²Å·ûºÏLinuxµÄÉ豸¹ÜÀí»úÖÆ£¬ÕâÀïÃæµÄdevtmpfsÊÇרÃÅÉè¼ÆÓÃÀ´¹ÜÀíÉ豸ÎļþµÄÎļþϵͳ¡£É豸Îļþ´´½¨ºÃÖ®ºó¾Í»áºÍ´´½¨Ê±Ö¸¶¨µÄÉ豸°ó¶¨£¬¼´Ê¹É豸ÒѾ­±»Ð¶ÔØÁË£¬ÈçҪɾ³ýÉ豸Îļþ£¬Ö»ÐèÒªÏñɾ³ýÆÕͨÎļþÒ»Ñùrm¼´¿É¡£ÀíÂÛÉÏÄ£¿éÃû(lsmod),É豸Ãû(/proc/devices)£¬É豸ÎļþÃû(/dev)²¢Ã»ÓÐʲô¹ØÏµ£¬ÍêÈ«¿ÉÒÔ²»Ò»Ñù£¬µ«ÊÇÔ­ÔòÉÏ»¹Êǽ¨Ò齫ÈýÕß½øÐÐͳһ£¬±ãÓÚ¹ÜÀí¡£

³ýÁËʹÓÃõ¿½ÅµÄÊÖ¶¯´´½¨É豸½ÚµãµÄ·½Ê½£¬ÎÒÃÇ»¹¿ÉÒÔÔÚÉ豸ԴÂëÖÐʹÓÃÏàÓ¦µÄ´ëʩʹÉ豸һµ©±»¼ÓÔØ¾Í×Ô¶¯´´½¨É豸Îļþ£¬×Ô¶¯´´½¨É豸ÎļþÐèÒªÎÒÃÇÔÚ±àÒëÄں˵Äʱºò»òÖÆ×÷¸ùÎļþϵͳµÄʱºò¾ÍºÃÏàÓ¦µÄÅäÖÃ:

Device Drivers ---> 
Generic Driver Options --->
[*]Maintain a devtmpfs filesystem to mount at /dev
[*] Automount devtmpfs at /dev,after the kernel mounted the rootfs

OR

ÖÆ×÷¸ùÎļþϵͳµÄÆô¶¯½Å±¾Ð´Èë

mount -t sysfs none sysfs /sys 
mdev -s //udevÒ²ÐÐ

ÓÐÁËÕâЩ׼±¸£¬Ö»ÐèÒªµ¼³öÏàÓ¦µÄÉ豸ÐÅÏ¢µ½"/sys"¾Í¿ÉÒÔ°´ÕÕÎÒÃǵÄÒªÇó×Ô¶¯´´½¨É豸Îļþ¡£Äں˸øÎÒÃÇÌṩÁËÏà¹ØµÄAPI

class_create(owner,name); 
struct device *device_create_vargs(struct class *cls, struct device
*parent,dev_t devt, void *drvdata,const char *fmt, va_list vargs);

void class_destroy(struct class *cls);
void device_destroy(struct class *cls, dev_t devt);

ÓÐÁËÕ⼸¸öº¯Êý£¬ÎÒÃǾͿÉÒÔÔÚÉ豸µÄxxx_init()ºÍxxx_exit()ÖзֱðÌîдÒÔϵĴúÂë¾Í¿ÉÒÔʵÏÖ×Ô¶¯µÄ´´½¨É¾³ýÉ豸Îļþ

/* ÔÚ/sysÖе¼³öÉ豸ÀàÐÅÏ¢ */ 
cls = class_create(THIS_MODULE,DEV_NAME);
/* ÔÚclsÖ¸ÏòµÄÀàÖд´½¨Ò»×é(¸ö)É豸Îļþ */
for(i= minor;i<(minor+cnt);i++){
devp = device_create(cls,NULL,MKDEV(major,i),NULL,"%s%d",DEV_NAME,i);
}

/* ÔÚclsÖ¸ÏòµÄÀàÖÐɾ³ýÒ»×é(¸ö)É豸Îļþ */ 
for(i= minor;i<(minor+cnt);i++){
device_destroy(cls,MKDEV(major,i));
}
/* ÔÚ/sysÖÐɾ³ýÉ豸ÀàÐÅÏ¢ */
class_destroy(cls); //Ò»¶¨ÒªÏÈÐ¶ÔØdeviceÔÙÐ¶ÔØclass

Íê³ÉÁËÕâЩ¹¤×÷£¬Ò»¸ö¼òµ¥µÄ×Ö·ûÉ豸Çý¶¯¾Í´î½¨Íê³ÉÁË£¬ÏÖÔھͿÉÒÔдһ¸öÓû§³ÌÐò½øÐвâÊÔÁË^ - ^

   
2254 ´Îä¯ÀÀ       27
 
Ïà¹ØÎÄÕÂ

ÔÆ¼ÆËãµÄ¼Ü¹¹
¶ÔÔÆ¼ÆËã·þÎñÄ£ÐÍ
ÔÆ¼ÆËãºËÐļ¼ÊõÆÊÎö
Á˽âÔÆ¼ÆËãµÄ©¶´
 
Ïà¹ØÎĵµ

ÔÆ¼ÆËã¼ò½é
ÔÆ¼ÆËã¼ò½éÓëÔÆ°²È«
ÏÂÒ»´úÍøÂç¼ÆËã--ÔÆ¼ÆËã
ÈídzÎöÔÆ¼ÆËã
 
Ïà¹Ø¿Î³Ì

ÔÆ¼ÆËãÔ­ÀíÓëÓ¦ÓÃ
ÔÆ¼ÆËãÓ¦ÓÃÓ뿪·¢
CMMIÌåϵÓëʵ¼ù
»ùÓÚCMMI±ê×¼µÄÈí¼þÖÊÁ¿±£Ö¤
×îл¼Æ»®
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢ 6-12[ÏÃÃÅ]
È˹¤ÖÇÄÜ.»úÆ÷ѧϰTensorFlow 6-22[Ö±²¥]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 6-30[±±¾©]
ǶÈëʽÈí¼þ¼Ü¹¹-¸ß¼¶Êµ¼ù 7-9[±±¾©]
Óû§ÌåÑé¡¢Ò×ÓÃÐÔ²âÊÔÓëÆÀ¹À 7-25[Î÷°²]
ͼÊý¾Ý¿âÓë֪ʶͼÆ× 8-23[±±¾©]

ר¼ÒÊӽǿ´ITÓë¼Ü¹¹
Èí¼þ¼Ü¹¹Éè¼Æ
ÃæÏò·þÎñÌåϵ¼Ü¹¹ºÍÒµÎñ×é¼þµÄ˼¿¼
ÈËÈËÍøÒÆ¶¯¿ª·¢¼Ü¹¹
¼Ü¹¹¸¯»¯Ö®ÃÕ
̸ƽ̨¼´·þÎñPaaS
Ïà¹ØÅàѵ¿Î³Ì

ÔÆ¼ÆËãÔ­ÀíÓëÓ¦ÓÃ
Windows Azure ÔÆ¼ÆËãÓ¦ÓÃ

ĦÍÐÂÞÀ­ ÔÆÆ½Ì¨µÄ¹¹½¨ÓëÓ¦ÓÃ
ͨÓù«Ë¾GE DockerÔ­ÀíÓëʵ¼ù
ijÑз¢ÖÐÐÄ Openstackʵ¼ù
ÖªÃûµç×Ó¹«Ë¾ ÔÆÆ½Ì¨¼Ü¹¹ÓëÓ¦ÓÃ
ijµçÁ¦ÐÐÒµ »ùÓÚÔÆÆ½Ì¨¹¹½¨ÔÆ·þÎñ
ÔÆ¼ÆËãÓëWindows AzureÅàѵ
±±¾© ÔÆ¼ÆËãÔ­ÀíÓëÓ¦ÓÃ