reactos操作系统实现(127)

 从上面的代码里可以看到调用函数VfatAddEntry来添加文件或目录的入口,其实现的代码如下:

#001  NTSTATUS

#002  VfatAddEntry(

#003      IN PDEVICE_EXTENSION DeviceExt,

#004      IN PUNICODE_STRING NameU,

#005      IN PVFATFCB *Fcb,

#006      IN PVFATFCB ParentFcb,

#007      IN ULONG RequestedOptions,

#008      IN UCHAR ReqAttr)

#009  {

 

这里判断是使用扩展的FAT16或者FAT32

#010      if (DeviceExt->Flags & VCB_IS_FATX)

#011          return FATXAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr);

#012      else

 

这里使用原来的FAT16或者FAT32

#013          return FATAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr);

#014  }

 

接着来分析创建一个FAT入口函数FATAddEntry

#001  static NTSTATUS

#002  FATAddEntry(

#003      IN PDEVICE_EXTENSION DeviceExt,

#004      IN PUNICODE_STRING NameU,

#005      IN PVFATFCB* Fcb,

#006      IN PVFATFCB ParentFcb,

#007      IN ULONG RequestedOptions,

#008      IN UCHAR ReqAttr)

#009  {

#010      PVOID Context = NULL;

#011      PFAT_DIR_ENTRY pFatEntry;

#012      slot *pSlots;

#013      USHORT nbSlots = 0, j, posCar;

#014      PUCHAR Buffer;

#015      BOOLEAN needTilde = FALSE, needLong = FALSE;

#016      BOOLEAN lCaseBase = FALSE, uCaseBase, lCaseExt = FALSE, uCaseExt;

#017      ULONG CurrentCluster;

#018      LARGE_INTEGER SystemTime, FileOffset;

#019      NTSTATUS Status = STATUS_SUCCESS;

#020      ULONG size;

#021      long i;

#022 

#023      OEM_STRING NameA;

#024      CHAR aName[13];

#025      BOOLEAN IsNameLegal;

#026      BOOLEAN SpacesFound;

#027 

#028      VFAT_DIRENTRY_CONTEXT DirContext;

#029      WCHAR LongNameBuffer[LONGNAME_MAX_LENGTH + 1];

#030      WCHAR ShortNameBuffer[13];

#031 

#032      DPRINT("addEntry: Name='%wZ', Dir='%wZ'/n", NameU, &ParentFcb->PathNameU);

#033 

#034      DirContext.LongNameU = *NameU;

#035 

#036      /* nb of entry needed for long name+normal entry */

 

计算一个FAT入口的占用内存大小。

#037      nbSlots = (DirContext.LongNameU.Length / sizeof(WCHAR) + 12) / 13 + 1;

#038      DPRINT("NameLen= %d, nbSlots =%d/n", DirContext.LongNameU.Length / sizeof(WCHAR), nbSlots);

 

分配FAT的入口内存。

#039      Buffer = ExAllocatePoolWithTag(NonPagedPool, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY), TAG_VFAT);

#040      if (Buffer == NULL)

#041      {

#042          return STATUS_INSUFFICIENT_RESOURCES;

#043      }

#044      RtlZeroMemory(Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY));

#045      pSlots = (slot *) Buffer;

#046 

#047      NameA.Buffer = aName;

#048      NameA.Length = 0;

#049      NameA.MaximumLength = sizeof(aName);

#050 

#051      DirContext.ShortNameU.Buffer = ShortNameBuffer;

#052      DirContext.ShortNameU.Length = 0;

#053      DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);

#054 

#055      RtlZeroMemory(&DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));

#056 

 

判断文件名称是否符合DOS里的8.3的文件命名格式。

#057      IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.LongNameU, &NameA, &SpacesFound);

#058 

#059      if (!IsNameLegal || SpacesFound)

#060      {

 

如果是非法的文件名称,或者包括有空格,就进入下面的处理。

#061          GENERATE_NAME_CONTEXT NameContext;

#062          VFAT_DIRENTRY_CONTEXT SearchContext;

#063          WCHAR ShortSearchName[13];

#064          needTilde = TRUE;

#065          needLong = TRUE;

#066          RtlZeroMemory(&NameContext, sizeof(GENERATE_NAME_CONTEXT));

#067          SearchContext.LongNameU.Buffer = LongNameBuffer;

#068          SearchContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);

#069          SearchContext.ShortNameU.Buffer = ShortSearchName;

#070          SearchContext.ShortNameU.MaximumLength = sizeof(ShortSearchName);

#071 

 

尝试100次来分配新的文件名称,并找新分配的文件名是否已经存。

#072          for (i = 0; i < 100; i++)

#073          {

#074              RtlGenerate8dot3Name(&DirContext.LongNameU, FALSE, &NameContext, &DirContext.ShortNameU);

#075              DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;

#076                                           SearchContext.DirIndex = 0;

 

查找新分配的文件是否存在。

#077              Status = FindFile(DeviceExt, ParentFcb, &DirContext.ShortNameU, &SearchContext, TRUE);

#078              if (!NT_SUCCESS(Status))

#079              {

#080                  break;

#081              }

#082          }

 

尝试100次分配新的文件名称都失败,就直接返回创建文件失败。

#083          if (i == 100) /* FIXME : what to do after this ? */

#084          {

#085              ExFreePoolWithTag(Buffer, TAG_VFAT);

#086              return STATUS_UNSUCCESSFUL;

#087          }

 

这里就已经重新分配文件成功了,保存起来在后面使用。

#088          IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.ShortNameU, &NameA, &SpacesFound);

#089          aName[NameA.Length]=0;

#090      }

#091      else

#092      {

#093          aName[NameA.Length] = 0;

 

检查文件名称是否包括点分隔符。

#094          for (posCar = 0; posCar < DirContext.LongNameU.Length / sizeof(WCHAR); posCar++)

#095          {

#096              if (DirContext.LongNameU.Buffer[posCar] == L'.')

#097              {

#098                  break;

#099              }

#100          }

#101          /* check if the name and the extension contains upper case characters */

 

检查文件名称和扩展名称是否同为小写。

#102          RtlDowncaseUnicodeString(&DirContext.ShortNameU, &DirContext.LongNameU, FALSE);

#103          DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;

#104          uCaseBase = wcsncmp(DirContext.LongNameU.Buffer,

#105                              DirContext.ShortNameU.Buffer, posCar) ? TRUE : FALSE;

#106          if (posCar < DirContext.LongNameU.Length/sizeof(WCHAR))

#107          {

#108              i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar;

#109              uCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar,

#110                                 DirContext.ShortNameU.Buffer + posCar, i) ? TRUE : FALSE;

#111          }

#112          else

#113          {

#114              uCaseExt = FALSE;

#115          }

#116          /* check if the name and the extension contains lower case characters */

 

检查文件名称和扩展名称是否同为大写。

#117          RtlUpcaseUnicodeString(&DirContext.ShortNameU, &DirContext.LongNameU, FALSE);

#118          DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;

#119          lCaseBase = wcsncmp(DirContext.LongNameU.Buffer,

#120                              DirContext.ShortNameU.Buffer, posCar) ? TRUE : FALSE;

#121          if (posCar < DirContext.LongNameU.Length / sizeof(WCHAR))

#122          {

#123              i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar;

#124              lCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar,

#125                                 DirContext.ShortNameU.Buffer + posCar, i) ? TRUE : FALSE;

#126          }

#127          else

#128          {

#129              lCaseExt = FALSE;

#130          }

#131          if ((lCaseBase && uCaseBase) || (lCaseExt && uCaseExt))

#132          {

#133              needLong = TRUE;

#134          }

#135      }

#136      DPRINT("'%s', '%wZ', needTilde=%d, needLong=%d/n",

#137             aName, &DirContext.LongNameU, needTilde, needLong);

 

设置FAT入口的文件名称。

#138      memset(DirContext.DirEntry.Fat.ShortName, ' ', 11);

#139      for (i = 0; i < 8 && aName[i] && aName[i] != '.'; i++)

#140      {

#141          DirContext.DirEntry.Fat.Filename[i] = aName[i];

#142      }

#143      if (aName[i] == '.')

#144      {

#145          i++;

#146          for (j = 0; j < 3 && aName[i]; j++, i++)

#147          {

#148              DirContext.DirEntry.Fat.Ext[j] = aName[i];

#149          }

#150      }

#151      if (DirContext.DirEntry.Fat.Filename[0] == 0xe5)

#152      {

#153          DirContext.DirEntry.Fat.Filename[0] = 0x05;

#154      }

#155 

 

如果需要长文件名称。

#156      if (needLong)

#157      {

#158          RtlCopyMemory(LongNameBuffer, DirContext.LongNameU.Buffer, DirContext.LongNameU.Length);

#159          DirContext.LongNameU.Buffer = LongNameBuffer;

#160          DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);

#161          DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0;

#162          memset(DirContext.LongNameU.Buffer + DirContext.LongNameU.Length / sizeof(WCHAR) + 1, 0xff,

#163                 DirContext.LongNameU.MaximumLength - DirContext.LongNameU.Length - sizeof(WCHAR));

#164      }

#165      else

#166      {

 

这里是使用短文件名称。

#167          nbSlots = 1;

#168          if (lCaseBase)

#169          {

#170              DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_BASE;

#171          }

#172          if (lCaseExt)

#173          {

#174              DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_EXT;

#175          }

#176      }

#177 

#178      DPRINT ("dos name=%11.11s/n", DirContext.DirEntry.Fat.Filename);

#179 

#180      /* set attributes */

 

设置FAT的属性。

#181      DirContext.DirEntry.Fat.Attrib = ReqAttr;

#182      if (RequestedOptions & FILE_DIRECTORY_FILE)

#183      {

#184          DirContext.DirEntry.Fat.Attrib |= FILE_ATTRIBUTE_DIRECTORY;

#185      }

#186      /* set dates and times */

 

设置FAT创建的系统日期和时间。

#187      KeQuerySystemTime(&SystemTime);

#188      FsdSystemTimeToDosDateTime(DeviceExt, &SystemTime, &DirContext.DirEntry.Fat.CreationDate,

#189                                 &DirContext.DirEntry.Fat.CreationTime);

#190      DirContext.DirEntry.Fat.UpdateDate = DirContext.DirEntry.Fat.CreationDate;

#191      DirContext.DirEntry.Fat.UpdateTime = DirContext.DirEntry.Fat.CreationTime;

#192      DirContext.DirEntry.Fat.AccessDate = DirContext.DirEntry.Fat.CreationDate;

#193 

#194      if (needLong)

#195      {

#196          /* calculate checksum for 8.3 name */

#197          for (pSlots[0].alias_checksum = 0, i = 0; i < 11; i++)

#198          {

#199              pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7

#200                                       | ((pSlots[0].alias_checksum & 0xfe) >> 1))

#201                                       + DirContext.DirEntry.Fat.ShortName[i]);

#202          }

#203          /* construct slots and entry */

 

构造所有入口。

#204          for (i = nbSlots - 2; i >= 0; i--)

#205          {

#206              DPRINT("construct slot %d/n", i);

#207              pSlots[i].attr = 0xf;

#208              if (i)

#209              {

#210                  pSlots[i].id = (unsigned char)(nbSlots - i - 1);

#211              }

#212              else

#213              {

#214                  pSlots[i].id = (unsigned char)(nbSlots - i - 1 + 0x40);

#215              }

#216              pSlots[i].alias_checksum = pSlots[0].alias_checksum;

#217              RtlCopyMemory(pSlots[i].name0_4, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13, 10);

#218              RtlCopyMemory(pSlots[i].name5_10, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 5, 12);

#219              RtlCopyMemory(pSlots[i].name11_12, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 11, 4);

#220          }

#221      }

#222      /* try to find nbSlots contiguous entries frees in directory */

 

在这个目录里找到空闲位置。

#223      if (!vfatFindDirSpace(DeviceExt, ParentFcb, nbSlots, &DirContext.StartIndex))

#224      {

#225          ExFreePoolWithTag(Buffer, TAG_VFAT);

#226          return STATUS_DISK_FULL;

#227      }

#228      DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1;

#229      if (RequestedOptions & FILE_DIRECTORY_FILE)

#230      {

#231          CurrentCluster = 0;

#232          Status = NextCluster(DeviceExt, 0, &CurrentCluster, TRUE);

#233          if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))

#234          {

#235              ExFreePoolWithTag(Buffer, TAG_VFAT);

#236              if (!NT_SUCCESS(Status))

#237              {

#238                  return Status;

#239              }

#240              return STATUS_DISK_FULL;

#241          }

#242          if (DeviceExt->FatInfo.FatType == FAT32)

#243          {

#244              DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);

#245          }

#246          DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster;

#247      }

#248 

#249      i = DeviceExt->FatInfo.BytesPerCluster / sizeof(FAT_DIR_ENTRY);

#250      FileOffset.u.HighPart = 0;

#251      FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FAT_DIR_ENTRY);

#252      if (DirContext.StartIndex / i == DirContext.DirIndex / i)

#253      {

 

一个簇的处理。

#254          /* one cluster */

#255          CcPinRead(ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY),

#256                    TRUE, &Context, (PVOID*)&pFatEntry);

#257          if (nbSlots > 1)

#258          {

#259              RtlCopyMemory(pFatEntry, Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY));

#260          }

#261          RtlCopyMemory(pFatEntry + (nbSlots - 1), &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));

#262      }

#263      else

#264      {

 

二个簇的处理。

#265          /* two clusters */

#266          size = DeviceExt->FatInfo.BytesPerCluster -

#267                 (DirContext.StartIndex * sizeof(FAT_DIR_ENTRY)) % DeviceExt->FatInfo.BytesPerCluster;

#268          i = size / sizeof(FAT_DIR_ENTRY);

#269          CcPinRead(ParentFcb->FileObject, &FileOffset, size, TRUE,

#270                    &Context, (PVOID*)&pFatEntry);

#271          RtlCopyMemory(pFatEntry, Buffer, size);

#272          CcSetDirtyPinnedData(Context, NULL);

#273          CcUnpinData(Context);

#274          FileOffset.u.LowPart += size;

#275          CcPinRead(ParentFcb->FileObject, &FileOffset,

#276                    nbSlots * sizeof(FAT_DIR_ENTRY) - size,

#277                    TRUE, &Context, (PVOID*)&pFatEntry);

#278          if (nbSlots - 1 > i)

#279          {

#280              RtlCopyMemory(pFatEntry, (PVOID)(Buffer + size), (nbSlots - 1 - i) * sizeof(FAT_DIR_ENTRY));

#281          }

#282          RtlCopyMemory(pFatEntry + nbSlots - 1 - i, &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));

#283      }

#284      CcSetDirtyPinnedData(Context, NULL);

#285      CcUnpinData(Context);

#286 

#287      /* FIXME: check status */

#288      vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb);

#289 

#290      DPRINT("new : entry=%11.11s/n", (*Fcb)->entry.Fat.Filename);

#291      DPRINT("new : entry=%11.11s/n", DirContext.DirEntry.Fat.Filename);

#292 

 

检查是否目录文件。

#293      if (RequestedOptions & FILE_DIRECTORY_FILE)

#294      {

#295          FileOffset.QuadPart = 0;

#296          CcPinRead((*Fcb)->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE,

#297                    &Context, (PVOID*)&pFatEntry);

#298          /* clear the new directory cluster */

#299          RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);

 

在文件目录里创建缺省目录'.' '..'

#300          /* create '.' and '..' */

#301          RtlCopyMemory(&pFatEntry[0].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);

#302          RtlCopyMemory(pFatEntry[0].ShortName, ".          ", 11);

#303          RtlCopyMemory(&pFatEntry[1].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);

#304          RtlCopyMemory(pFatEntry[1].ShortName, "..         ", 11);

#305          pFatEntry[1].FirstCluster = ParentFcb->entry.Fat.FirstCluster;

#306          pFatEntry[1].FirstClusterHigh = ParentFcb->entry.Fat.FirstClusterHigh;

 

如果这里根目录,就设置父目录为空,不能再往上查看。

#307          if (vfatFCBIsRoot(ParentFcb))

#308          {

#309              pFatEntry[1].FirstCluster = 0;

#310              pFatEntry[1].FirstClusterHigh = 0;

#311          }

#312          CcSetDirtyPinnedData(Context, NULL);

#313          CcUnpinData(Context);

#314      }

#315      ExFreePoolWithTag(Buffer, TAG_VFAT);

#316      DPRINT("addentry ok/n");

#317      return STATUS_SUCCESS;

#318  }

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caimouse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值